-- phpMyAdmin SQL Dump
-- version 2.11.9.6
-- http://www.phpmyadmin.net
--
-- Servidor: localhost:3306
-- Tiempo de generación: 22-02-2012 a las 13:06:12
-- Versión del servidor: 5.0.68
-- Versión de PHP: 5.2.6

SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";


/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;

--
-- Base de datos: `soporte_oraculus`
--
DROP DATABASE `soporte_oraculus`;
CREATE DATABASE `soporte_oraculus` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
USE `soporte_oraculus`;

-- --------------------------------------------------------

--
-- Estructura de tabla para la tabla `CATEGORIAS`
--

CREATE TABLE IF NOT EXISTS `CATEGORIAS` (
  `ID_CATEGORIA` tinyint(3) NOT NULL auto_increment,
  `CATEGORIA` varchar(25) character set utf8 NOT NULL,
  PRIMARY KEY  (`ID_CATEGORIA`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=9 ;

--
-- Volcar la base de datos para la tabla `CATEGORIAS`
--

INSERT INTO `CATEGORIAS` (`ID_CATEGORIA`, `CATEGORIA`) VALUES
(1, 'OCA'),
(2, 'OCP'),
(3, 'PLSQL'),
(4, 'SQL'),
(5, 'UNIX'),
(6, 'ORACLE'),
(7, 'RAC'),
(8, 'SCRIPTS');

-- --------------------------------------------------------

--
-- Estructura de tabla para la tabla `CAT_ENTRADAS`
--

CREATE TABLE IF NOT EXISTS `CAT_ENTRADAS` (
  `ID_ENTRADA` int(11) NOT NULL,
  `ID_SUBCATEGORIA` tinyint(3) NOT NULL,
  `ID_SIGUIENTE` int(11) default NULL,
  `ID_ANTERIOR` int(11) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

--
-- Volcar la base de datos para la tabla `CAT_ENTRADAS`
--

INSERT INTO `CAT_ENTRADAS` (`ID_ENTRADA`, `ID_SUBCATEGORIA`, `ID_SIGUIENTE`, `ID_ANTERIOR`) VALUES
(31, 33, NULL, NULL),
(45, 42, NULL, NULL),
(42, 39, NULL, NULL),
(41, 38, NULL, NULL),
(40, 38, NULL, NULL),
(39, 37, NULL, NULL),
(38, 36, NULL, NULL),
(36, 35, NULL, NULL),
(44, 41, NULL, NULL),
(46, 42, NULL, NULL),
(48, 42, NULL, NULL),
(49, 38, NULL, NULL),
(50, 43, NULL, NULL),
(51, 38, NULL, NULL),
(52, 44, NULL, NULL),
(53, 44, NULL, NULL),
(54, 43, NULL, NULL),
(55, 45, NULL, NULL),
(56, 43, NULL, NULL),
(57, 41, NULL, NULL),
(58, 43, NULL, NULL),
(58, 44, NULL, NULL),
(59, 43, NULL, NULL),
(60, 44, NULL, NULL),
(61, 44, NULL, NULL),
(62, 43, NULL, NULL),
(63, 43, NULL, NULL),
(64, 44, NULL, NULL),
(65, 36, NULL, NULL),
(66, 36, NULL, NULL),
(67, 36, NULL, NULL),
(68, 39, NULL, NULL),
(68, 47, NULL, NULL),
(69, 39, NULL, NULL),
(70, 49, NULL, NULL),
(71, 50, NULL, NULL),
(72, 51, NULL, NULL);

-- --------------------------------------------------------

--
-- Estructura de tabla para la tabla `ENTRADAS`
--

CREATE TABLE IF NOT EXISTS `ENTRADAS` (
  `ID_ENTRADA` int(11) NOT NULL auto_increment,
  `ID_USUARIO` tinyint(3) NOT NULL,
  `TITULO` varchar(100) character set utf8 default NULL,
  `DESCRIPCION` varchar(500) character set utf8 default NULL,
  `FECHA` date default NULL,
  `ACTIVO` tinyint(1) NOT NULL,
  PRIMARY KEY  (`ID_ENTRADA`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=73 ;

--
-- Volcar la base de datos para la tabla `ENTRADAS`
--

INSERT INTO `ENTRADAS` (`ID_ENTRADA`, `ID_USUARIO`, `TITULO`, `DESCRIPCION`, `FECHA`, `ACTIVO`) VALUES
(31, 1, 'Trabajar con secuencias', '<div class="desc_parrafo_lista">\r\n    Create sequence.\r\n    Alter sequence.\r\n    Utilizar secuencia.\r\n</div>\r\n	', '2011-12-29', 1),
(36, 1, 'Monitoreo espacio filesystems', '<div class="desc_parrafo_lista">\r\nTipo post: Script\r\n</div>', '2011-12-30', 1),
(38, 1, 'Crear Directorios', '<div class="desc_parrafo_lista">\r\n	Crear directorios, dar permisos.\r\n</div>', '2012-01-01', 1),
(39, 1, 'File Descriptor', '<div class="desc_parrafo_lista">\r\nDefinicion, Tipos, monitoreo.\r\n</div>\r\n', '2012-01-01', 1),
(40, 1, 'Crear Logs', '<div class="desc_parrafo_lista">\r\nTipo: Script Unix\r\n</div>\r\n', '2012-01-01', 1),
(41, 1, 'Ejecutar SQLPLUS desde Linux', '<div class="desc_parrafo_lista">\r\nTipo: Script SQLPLUS\r\n</div>\r\n	', '2012-01-01', 1),
(42, 1, 'Monitorizar uso de la memoria', '<div class="desc_parrafo_lista">\r\nTipo: Script Unix\r\n</div>		', '2012-01-01', 1),
(44, 1, 'TRIGGER para sentencias DML', '<div class="desc_parrafo_lista">\r\nCrear Trigger, Vista relacionada, Parametros.\r\n</div>		', '2012-01-03', 1),
(45, 1, 'Informacion Foreing keys de una tabla', '<div class="desc_parrafo_lista">\r\nTipo: Script SQL\r\n</div>', '2012-01-03', 1),
(46, 1, 'Informacion SQL ejecutado sesiones activas', '<div class="desc_parrafo_lista">\r\nTipo: Script SQL\r\n</div>', '2012-01-03', 1),
(48, 1, 'Informacion Indices de una tabla.', '<div class="desc_parrafo_lista">\r\nTipo: Script SQL\r\n</div>', '2012-01-03', 1),
(49, 1, 'Script Export listado de tablas', '<div class="desc_parrafo_lista">\r\nTipo: Script SQLPLUS\r\n</div>		', '2012-01-04', 1),
(50, 1, 'Eliminar Indices de una tabla', '<div class="desc_parrafo_lista">\r\nTipo:  Bloque PLSQL\r\n</div>', '2012-01-04', 1),
(51, 1, 'Spool Generico', '<div class="desc_parrafo_lista">\r\nTipo:  Bloque SQLPLUS\r\n</div>\r\n	', '2012-01-04', 1),
(52, 1, 'PLSQL Introduccion y bloques', '<div class="desc_parrafo_lista">\r\nTipos de datos, bloques anonimos y bloques anidados\r\n</div>', '2012-01-05', 1),
(53, 1, 'PLSQL: Estructuras de control', '<div class="desc_parrafo_lista">\r\nIf, LOOP, FOR, WHILE, GOTO\r\n</div>', '2012-01-05', 1),
(54, 1, 'Colecciones', '<div class="desc_parrafo_lista">\r\nNested tables, Varrays y Arrays asociados\r\n</div>\r\n	', '2012-01-05', 1),
(55, 1, 'BULK COLLECT', '<div class="desc_parrafo_lista">\r\nDevolver varios registros en una sentencia SELECT INTO.\r\n</div>', '2012-01-06', 1),
(56, 1, 'Records', '<div class="desc_parrafo_lista">\r\nDevolver varios registros en una sentencia SELECT INTO.\r\n</div>\r\n	', '2012-01-06', 1),
(57, 1, 'DML Manipulacion de datos en PLSQL', '<div class="desc_parrafo_lista">\r\nEjemplos de sentencias DML en bloques de PLSQL\r\n</div>', '2012-01-06', 1),
(58, 1, 'Cursores', '<div class="desc_parrafo_lista">\r\nCursores implicitos y explicitos.\r\n</div>', '2012-01-06', 1),
(59, 1, 'Cursores Variables', '<div class="desc_parrafo_lista">\r\nDeclaraci&oacute;n, OPEN - FOR, FECTCH, CLOSE.\r\n</div>	', '2012-01-09', 1),
(60, 1, 'SELECT .. FOR UPDATE', '<div class="desc_parrafo_lista">\r\nDeclaracion, Filosofia de uso\r\n</div>', '2012-01-09', 1),
(61, 1, 'EXECUTE IMMEDIATE', '<div class="desc_parrafo_lista">\r\nSQL Dinamico, USING IN\r\n</div>', '2012-01-10', 1),
(62, 1, 'Subprocesos', '<div class="desc_parrafo_lista">\r\nProcedimientos y Funciones\r\n</div>\r\n', '2012-01-10', 1),
(63, 1, 'Paquetes', '<div class="desc_parrafo_lista">\r\nCabecera y cuerpo\r\n</div>	', '2012-01-10', 1),
(64, 1, 'Manejo de Excepciones', '<div class="desc_parrafo_lista">\r\nManejo. Excepciones definidas por el usuario. Relanzado\r\n</div>		', '2012-01-10', 1),
(65, 1, 'DataPump Export', '<div class="desc_parrafo_lista">\r\nModos de trabajo. Parametros de condiguraci&oacute;n\r\n</div>', '2012-01-11', 1),
(66, 1, 'Ejemplos DataPump Export', '<div class="desc_parrafo_lista">\r\nTipo: Scripts Export\r\n</div>	', '2012-01-11', 1),
(67, 1, 'DataPump Import', '<div class="desc_parrafo_lista">\r\nModos de operacion. Comandos. Ejemplos\r\n</div>', '2012-01-12', 1),
(68, 1, 'Monitorizar sesiones', '<div class="desc_parrafo_lista">\r\nIdentificar PID con SID. Parar proceso.\r\n</div>	', '2012-01-12', 1),
(69, 1, 'Monitorizar Bloqueos', '<div class="desc_parrafo_lista">\r\nTipo: Script SQL\r\n</div>', '2012-01-13', 1),
(70, 1, 'Ejemplo Estudio bloqueos', '<div class="desc_parrafo_lista">\r\nBloqueo entre sesiones.\r\n</div>	', '2012-01-16', 1),
(71, 1, 'Bloqueos', '<div class="desc_parrafo_lista">\r\nTipos de bloqueos. Modos de bloqueo.\r\n</div>	', '2012-01-16', 1),
(72, 1, 'Flashback Recovery Area', '<div class="desc_parrafo_lista">\r\nConfiguraciÃ³n. GestiÃ³n.\r\n</div>	', '2012-01-19', 1);

-- --------------------------------------------------------

--
-- Estructura de tabla para la tabla `ENTRADA_TAG`
--

CREATE TABLE IF NOT EXISTS `ENTRADA_TAG` (
  `ID_ENTRADA` int(11) NOT NULL,
  `ID_TAG` tinyint(3) NOT NULL,
  KEY `ID_ENTRADA` (`ID_ENTRADA`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

--
-- Volcar la base de datos para la tabla `ENTRADA_TAG`
--

INSERT INTO `ENTRADA_TAG` (`ID_ENTRADA`, `ID_TAG`) VALUES
(31, 15),
(53, 24),
(51, 20),
(50, 27),
(50, 28),
(50, 26),
(49, 20),
(48, 19),
(46, 21),
(45, 25),
(45, 19),
(44, 19),
(42, 21),
(42, 24),
(41, 23),
(40, 22),
(39, 21),
(38, 20),
(38, 19),
(36, 17),
(36, 16),
(36, 18),
(55, 29),
(54, 19),
(53, 27),
(56, 19),
(57, 27),
(58, 26),
(59, 26),
(60, 26),
(61, 26),
(61, 27),
(62, 19),
(62, 27),
(63, 19),
(63, 30),
(64, 27),
(64, 31),
(65, 20),
(66, 20),
(68, 33),
(68, 34),
(69, 35),
(70, 35),
(70, 31),
(71, 35),
(72, 17),
(72, 36);

-- --------------------------------------------------------

--
-- Estructura de tabla para la tabla `ENTRADA_TEXTO`
--

CREATE TABLE IF NOT EXISTS `ENTRADA_TEXTO` (
  `ID_ENTRADA` int(11) NOT NULL,
  `TEXTO` text character set utf8 NOT NULL,
  KEY `ID_ENTRADA` (`ID_ENTRADA`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

--
-- Volcar la base de datos para la tabla `ENTRADA_TEXTO`
--

INSERT INTO `ENTRADA_TEXTO` (`ID_ENTRADA`, `TEXTO`) VALUES
(31, '<h3>1. CREAR SECUENCIA</h3>\r\n\r\n<div class="parrafo" align="justify">\r\nLa sintaxis de para crear una secuencia en Oracle ser&iacute;a:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>CREATE SEQUENCE MiSecuencia\r\n   INCREMENT BY n\r\n   START WITH n\r\n   {MAX VALUE n | NOMAXVALUE}\r\n   {MIN VALUE N | NOMINVALUE}\r\n   {CYCLE | NOCYCLE}\r\n   {CACHE N | NOCACHE}\r\n   {ORDER | NOORDER};\r\n   \r\n</p></pre></blockquote>\r\n\r\n<div class="parrafo" align="justify">\r\nParametros:\r\n</div>\r\n<div class="parrafo" align="justify">\r\nINCREMENT BY n: Indica el incremento que va a haber entre elementos consecutivos de una secuencia va a ser de n unidades. Con este parametro y con los parametros MAX VALUE  y MIN VALUE podemos generar secuencias ascendentes o descendentes, utilizando numeros positivos o negativos. Por defecto es 1.\r\n</div>\r\n<div class="parrafo" align="justify">\r\nSTART WITH n: Ser&aacute; el elemento inicial de la secuencia. Por defecto es 1.\r\n</div>\r\n<div class="parrafo" align="justify">\r\nMAX VALUE: El maximo valor que va a adquirir la secuencia. Tiene que ser mayor o igual que el parametro INCREMENT BY (en valor absoluto). NOMAXVALUE especificamos que el valor maximo de la secuencia sera 10 elevado a 27.\r\n</div>\r\n<div class="parrafo" align="justify">\r\nMIN VALUE: El minimo valor que va a adquirir la secuencia. En el caso de secuencias descendentes sera de -10 elevado a 26.\r\n</div>\r\n<div class="parrafo" align="justify">\r\nCYCLE | NOCYCLE: Configuramos si la secuencia es ciclica o no.\r\n</div>\r\n<div class="parrafo" align="justify">\r\nCACHE n: Indicamos el numero valores que se van a cargar en memoria.\r\n</div>\r\n<div class="parrafo" align="justify">\r\nEjemplo:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>SQL&GT;CREATE SEQUENCE POCO_SECUENCIA\r\nMINVALUE 1\r\nMAXVALUE 100\r\nSTART WITH 1\r\nCYCLE\r\nINCREMENT BY 1 CACHE 20;\r\n\r\n</p></pre></blockquote>\r\n\r\n<h3>2. ALTER SEQUENCE</h3>\r\n<div class="parrafo" align="justify">\r\nUtilizando el ejemplo anterior vamos a modificar la secuencia para que no sea ciclica.\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>SQL&GT; ATLER SEQUENCE POCO_SECUENCIA NOCYCLE;\r\n\r\n</p></pre></blockquote>\r\n<h3>3.UTILIZAR SECUENCIA </h3>\r\n<div class="parrafo" align="justify">\r\nPodemos utilizar una secuencia utilizando la propiedad nextval de la secuencia.\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>SQL&GT; INSERT INTO POCO_CAMBEST  VALUES (POCO_SECUENCIA.NEXTVAL, ''Prueba'');\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nPara saber en que valor se encuntra la secuencia podremos hacer:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>SQL&GT; SELECT POCO_SECUENCIA.nextval FROM dual;\r\n\r\n</p></pre></blockquote>\r\n\r\n<h3>4.VISTAS RELACIONADAS </h3>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>SQL&GT;  select table_name from dictionary where table_name like ''%SEQUENCES%'';\r\n\r\nTABLE_NAME\r\n------------------------------\r\nUSER_SEQUENCES\r\nALL_SEQUENCES\r\nDBA_SEQUENCES\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nPara ver la estructura de una de estas tablas haremos:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>SQL&GT; DESC USER_SEQUENCES\r\n\r\nSEQUENCE_NAME                            NOT NULL VARCHAR2(30)\r\nMIN_VALUE                                 NUMBER\r\nMAX_VALUE                                 NUMBER\r\nINCREMENT_BY                             NOT NULL NUMBER\r\nCYCLE_FLAG                                VARCHAR2(1)\r\nORDER_FLAG                                VARCHAR2(1)\r\nCACHE_SIZE                               NOT NULL NUMBER\r\nLAST_NUMBER                              NOT NULL NUMBER\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nComo valor rese&ntilde;able esta la columna LAST_NUMBER. El valor almacenado en esta columna se actualiza cada vez que se recarga la cache de la secuencia.\r\n</div>'),
(36, '<div class="parrafo" align="justify">\r\nEl script que podemos utilizar para el monitoreo de la ocupacion de nuestros filesystems es:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>THRESHOLD=95\r\ndf -H -P | grep -vE ''^Filesystem|tmpfs'' | awk ''{ print $5 " " $1 }'' | grep -v docs | while read output;\r\ndo\r\n  fspace=$(echo $output | awk ''{ print $1}'' | cut -d''%'' -f1  )\r\n  fs=$(echo $output | awk ''{ print $2 }'' )\r\n  if [ $fspace -ge $THRESHOLD ]; then\r\n    echo "WARNING Nos quedamos sin espacio "$fs ($fspace%)" on $(hostname) as on $(date)"\r\n  fi\r\ndone\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nComo vemos la variable THRESHOLD se edita para recibir un mensaje de Warning cuando la ocupacion supera ese umbral.\r\n</div>\r\n<div class="parrafo" align="justify">\r\nEste script puede ser util, cuando por el motivo que sea estamos generando mucho Redo y para evitar que se nos llene el filesystem de los archiver.\r\n</div>\r\n<div class="parrafo" align="justify">\r\nPara hacer automatica la ejecucion de este script lo podemos meter en un bucle while true y utilizando el comando sleep.\r\n</div>\r\n'),
(38, '<div class="parrafo" align="justify">\r\nUn consejo antes de modificar algun valor de vuestra base de datos es aseguraros una marcha atras, vamos un backup de la tabla o tablas que se van a modificar, simplemente para aseguraros que dejais la base de datos tal y como estaba en el caso que las cosas no salgan como habiais previsto.\r\n</div>\r\n<div class="parrafo" align="justify">\r\nPara realizar este backup, podemos utilizar varios metodos, pero yo principalmente prefiero usas el mecanismo de Import/Export que proporciona Oracle. Inicialmente se utilizaba los comandos exp e imp, pero con la utilidad DataPump da mucha mas flexibilidad.\r\n</div>\r\n<div class="parrafo" align="justify">\r\nAntes de empezar a utilizar el export con DataPump tenemos que crear el directorio o directorios donde vamos a dejar los ficheros resultantes. Un directorio en Oracle es un objeto de base de datos asociado a un path fisico.\r\n</div>\r\n<div class="parrafo" align="justify">\r\nLos pasos que hago antes de hacer un export son:\r\n</div>\r\n<div class="parrafo" align="justify">\r\n1.- Miramos en el arbol de directorios donde dejar nuestros ficheros.\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>> df -h\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\n2.- Creamos el directorio\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>SQL&gt; CREATE DIRECTORY DUMP_DIR AS ''/u01/app/oracle/backup'';\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\n3.- Damos permisos de escritura\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>SQL&gt; GRANT read, write ON DIRECTORY DUMP_DIR TO MOGU;\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\n3.- Lanzamos el expdp\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>> nohup expdp parfile=\\''export_file.txt\\'' &\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nLa vista que aporta informacion sobre los directorios de Oracle es ALL_DIRECTORIES.\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>SQL&GT; desc ALL_DIRECTORIES\r\n Name                                  	Null?	Type\r\n ----------------------------------------- -------- ----------------------------\r\n OWNER                                 	NOT NULL VARCHAR2(30)\r\n DIRECTORY_NAME                       	NOT NULL VARCHAR2(30)\r\n DIRECTORY_PATH                        VARCHAR2(4000)\r\n \r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nPara borrar directorios haremos:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif"><pre><p>\r\nSQL&GT; DROP DIRECTORY DUMP_DIR;\r\n</p></pre></blockquote>\r\n'),
(39, '<div class="parrafo" align="justify">\r\nLos file descriptor es un numero provisto por el sistema operativo, con el cual los procesos pueden mandar bytes. En Unix muchas cosas pueden ser File Descriptor:\r\n<div class="parrafo_lista_sub">\r\n-- Pipes</br>\r\n-- Sockets</br>\r\n-- FIFOs</br>\r\n-- Conexiones con perifericos\r\n</div>\r\n</div>\r\n<div class="parrafo" align="justify">\r\nLos primeros file descriptos que tiene el sistema son\r\n<div class="parrafo_lista_sub">\r\n0 - Entrada estandar</br>\r\n1 - Salida estandar</br>\r\n2 - Salida de error</br>\r\n</div>\r\n</div>\r\n<div class="parrafo" align="justify">\r\nSi abriesemos otro fichero inmediatamente le asignaria el FD 3.\r\n</div>\r\n<div class="parrafo" align="justify">\r\nLas operaciones basicas que se realizan sobre los FD son:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>read(fd, buffer, tam)\r\nwrite(fd, buffer, tam)\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nEl numero de file descriptor es un parametro que se define en /etc/sysctl.conf\r\nTambien podemos saber donde se encuentra el numero maximo de file descriptor de nuestro kernel mirando:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>> more /proc/sys/fs/file-max\r\n> 8192\r\n\r\no\r\n\r\n> sysctl -a | grep fs.file-max\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nPara mirar el numero de FD que actualmente estan siendo usados haremos:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>> more /proc/sys/fs/file-nr\r\n> 8191\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nPara saber cuantos ficheros hay abiertos haremos\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>> lsof | wc -l\r\n> 10325\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nEn teoria los dos numeros anteriores deberian de ser iguales pero nos podemos encontrar que un file descriptor apunte a varios ficheros a la vez.\r\n</div>\r\n<div class="parrafo" align="justify">\r\nPara saber cuantos file descriptor tiene abierto un determinado proceso haremos:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>>ps -fea | grep oracle\r\n> 28290\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nEste peque&ntilde;o script te muestra como se distribuyen los FD entre los difernetes procesos de oracle:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>ps -fea | grep oracle | grep -v grep | while read salida\r\ndo\r\n pid=`echo $salida | awk ''{print $2}''`\r\n fd=`/usr/sbin/lsof -p $pid | wc -l`\r\n proces=`echo $salida | awk ''{print $8}''`\r\n echo "PID: ${pid}, PROCCESS: ${proces}, FD: ${fd}" >>log_fd.txt\r\ndone\r\n\r\nlsof +c 32| perl -lane ''$x{"$F[0]:$F[1]"}++;\r\nEND { print "$x{$_}	$_" for sort {$x{$a}<=>$x{$b}} keys %x}''\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nPodemos modificar el numero maximo de FD permitidos haciendo:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>\r\nvi /etc/sysctl.conf\r\n\r\nfs.file-max = 331287\r\n\r\nsysctl &minus;p\r\n</p></pre></blockquote>'),
(40, '<div class="parrafo" align="justify">\r\nEsta funci&oacute;n la desarroll&eacute; para ir registrando en un fichero y sacando a su vez por pantalla los diferentes eventos que se registraban en mis scripts, para ejecutarlo debemos editar la variable FICH_LOG con el nombre del fichero de log que queramos, tambi&eacute;n recomiendo concatenar el nombre del fichero con la variable fec para registrar la hora de ejecuci&oacute;n del script.\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>#! /bin/ksh\r\n\r\nfec=`date +%Y%m%d_%H%M%S`\r\nFICH_LOG=export_$fec.log\r\n\r\n##------------------------------------------------##\r\n## Function: LOG\r\n## Funcion que utilizamos para escribir las trazas.\r\n##------------------------------------------------##\r\nfunction LOG {\r\n\r\n     fecha=`date +%H:%M:%S`\r\n     echo "[ $fecha ]    "$1 >> $FICH_LOG\r\n         echo "[ $fecha ]  "$1\r\n\r\n return 0\r\n\r\n}\r\n\r\n##------------------------------------------------##\r\n## MAIN\r\n##------------------------------------------------##\r\n\r\nLOG "-- Prueba LOG"\r\n\r\n</p></pre></blockquote>'),
(41, '<div class="parrafo" align="justify">\r\nPublico el codigo que utilizo para ejecutar scripts o bloques de PLSQL desde UNIX. Con las ventajas de poder ejecutar el script en background y con el control de errores de Oracle ORA-xxxx.\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif"><pre><p>\r\n#! /bin/ksh\r\n\r\nfec=`date +%Y%m%d_%H%M%S`\r\nFICH_LOG=backup_$fec.log\r\n\r\nSQLPLUS=$ORACLE_HOME/bin/sqlplus; export SQLPLUS\r\nUSRPWD="OPGE/temporal"  export USRPWD\r\n\r\nrm -f /tmp/.backup*.tmp 2>/dev/null\r\nftmp=/tmp/.backup$$_${RANDOM}.tmp\r\n\r\n	$SQLPLUS -s /nolog <<[EOSQL] > $ftmp\r\n	connect $USRPWD;\r\n	set lin 160 pages 500 timing on\r\n	@stats_$tabla.sql\r\n	quit\r\n[EOSQL]\r\n	ca_err=`grep "^ORA-" $ftmp | wc -l`\r\n	if [ $ca_err -gt 0 ]; then\r\n		LOG "ERROR: Ejecutando stats_$tabla.sql"\r\n		cat $ftmp | tee -a $FICH_LOG                 \r\n		exit 1\r\n	fi\r\n	\r\n</p></pre></blockquote>\r\n\r\n<div class="parrafo" align="justify">\r\nUna vez creado el script le damos permisos de ejecucion y lo lanzamos con nohup.\r\n</div>\r\n'),
(42, '<div class="parrafo" align="justify">\r\nEste bucle infinito que muestra cada 4 segundos la utilizacion de la memoria.\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>while [ /bin/true ] ; \r\n do \r\n clear \r\n ps aux | sort -rnk 4 | head -n 5 | cat <(echo `date`) - | tee -a high_mem.log \r\n sleep 4 \r\n done\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nDesglosamos algunos de los comandos que estamos utilizando en este script.\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>>ps aux\r\n\r\nUSER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nLas columnas que aparecen son:\r\n<div class="parrafo_lista_sub">\r\nUSER: Usuario propietario del proceso.</br>\r\nPID: Identificador del proceso.</br>\r\n%CPU: Porcentaje de utilizacion de la CPU.</br>\r\n%MEN: Porcentaje de la memoria utilizada.</br>\r\nVSZ: Memoria virtual utilizada (kbytes)</br>\r\nRSS: Memoria real utilizada (kbytes).</br>\r\nSTAT: Estado en el que se ecuentra el proceso:\r\n<div class="parrafo_lista_sub">\r\n	-- R running</br>\r\n	-- S sleeping</br>\r\n	-- Z zombie (proceso que ha muerto, pero su padre no se ha hecho cargo)</br>\r\n	-- T stopped.</br>\r\n</div>\r\n</div>\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>>sort -rnk 4\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nsort -- ordena los datos que se le pasan.\r\n<div class="parrafo_lista_sub">\r\n-r de mayor a menor</br>\r\n-n interpreta los datos como si fuesen numeros</br>\r\n-k n ordena los datos segun la columna en la posicion n</br>\r\n</div>\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>>head -n 5\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nEsto nos muestra los 5 primeros elementos.\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>> cat <(echo `date`) - | tee -a high_mem.log \r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nLa primera parte concatena con a la entrada la fecha. y la segunda tee almacena en el fichero y saca por pantalla el contenido\r\n</div>'),
(44, '<div class="parrafo" align="justify">\r\nEn este post publicamos el c&oacute;mo trabajar con triggers ante eventos producidos por sentencias DML (insert, update, delete). \r\n</div>\r\n<div class="parrafo" align="justify">\r\nUn trigger es un procedimiento o bloque de PLSQL que se ejecutara cuando se den unas determinadas circunstancias. Para poder crear un trigger es necesario que el usuario tenga el privilegio de ADMINISTER DATABASE TRIGGER, ademas el usuario tiene que tener los privilegios nacesarios para ejecutar el procedimiento asociado al trigger. \r\n</div>\r\n<div class="parrafo" align="justify">\r\nSintaxis: \r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>CREATE [OR REPLACE] TRIGGER <trigger_name> \r\n  {BEFORE|AFTER} {INSERT|DELETE|UPDATE} ON <table_name> \r\n  [REFERENCING [NEW AS <new_row_name>] [OLD AS <old_row_name>]] \r\n  [FOR EACH ROW [WHEN (<trigger_condition>)]] \r\n <trigger_body> \r\n \r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\n-- {BEFORE|AFTER} {INSERT|DELETE|UPDATE} ON <table_name>:Podemos combinar varios disparadores de eventos con el prametro OR \r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>... INSERT ON R ... \r\n... INSERT OR DELETE OR UPDATE ON R ... \r\n   ... UPDATE OF A, B OR INSERT ON R ... \r\n\r\n   </p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nAdemas con el evento de update podemos indicar que columnas de la tabla dispararan el trigger. \r\n</div>\r\n<div class="parrafo" align="justify">\r\n-FOR EACH ROW [WHEN (<trigger_condition>)]] :Con esta clausula hacemos que el trigguer evale cada una de las filas afectadas por la sentencia DML y ejecute el bloque de PLSQL, si se cumple trigger_condition. \r\n</div>\r\n<div class="parrafo" align="justify">\r\n-<trigger_body>: En el cuerpo del trigguer NEW y OLD deben de precederse por :\r\n</div>\r\n<div class="parrafo" align="justify">\r\n-[REFERENCING [NEW AS <new_row_name>] [OLD AS <old_row_name>]] Utilizaremos esta clausula para asignar nuevos valores a las variables NEW y OLD. \r\n</div>\r\n\r\n<h3>EJEMPLOS: </h3>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>SQL> CREATE TRIGGER trig1 \r\n    AFTER INSERT ON T4 \r\n    REFERENCING NEW AS newRow \r\n    FOR EACH ROW \r\n    WHEN (newRow.a <= 10) \r\n    BEGIN \r\n        INSERT INTO T5 VALUES(:newRow.b, :newRow.a); \r\n    END trig1;\r\n	\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nEn el caso de que el bloque de PLSQL tenga errores de sintaxis recibiremos este warning: Trigger created with compilation errors. Para obtener mas informacion de los errores haremos: \r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>SQL> SHOW ERRORS TRIGGER <trigger_name>; \r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nPara habilitar o deshabilitar triggers haremos: \r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>SQL&GT; ALTER TRIGGER MiTrigger ENABLE|DISABLE; \r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nLa vista que proporciona Oracle para obtener informacion de nuestros listener es USER_TRIGGERS: \r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>SQL&GT; select \r\n    trigger_type, \r\n    triggering_event, \r\n    table_name, \r\n    referencing_names, \r\n    trigger_body \r\nfrom user_triggers \r\nwhere trigger_name = ''<trigger_name>''; \r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nPara borrar un trigger haremos: \r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>SQL&GT; DROP TRIGGER <trigger_name>; \r\n</p></pre></blockquote>'),
(45, '<div class="parrafo" align="justify">\r\nEn este post presentamos un script que permite extraer las foreing keys de una tabla, de la primary key y de la tabla padre de la que se nutre\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>	SQL> SELECT\r\n		B.CONSTRAINT_NAME FK_CONST,\r\n		A.CONSTRAINT_NAME PK_PADRE,\r\n		A.TABLE_NAME TABLA_PADRE\r\n	FROM USER_CONSTRAINTS A,\r\n	(SELECT\r\n		CONSTRAINT_NAME,\r\n		TABLE_NAME,\r\n		R_CONSTRAINT_NAME\r\n	 FROM USER_CONSTRAINTS\r\n	 WHERE\r\n		TABLE_NAME=''&tabla''\r\n		AND CONSTRAINT_TYPE=''R'') B\r\n	WHERE\r\n		A.CONSTRAINT_NAME=B.R_CONSTRAINT_NAME;\r\n		\r\n	Enter value for tabla: PPGA_PROMOACTPER\r\n	old  13:        TABLE_NAME=''&tabla''\r\n	new  13:        TABLE_NAME=''PPGA_PROMOACTPER''\r\n\r\n	FK_CONST                       PK_PADRE                       TABLA_PADRE\r\n	------------------------------ ------------------------------ ------------------------------\r\n	FK_PROMOACTPER_TIPACTPER       PK_ACTPERIODICAS               PPGA_TIPACTPER\r\n\r\n</p></pre></blockquote>\r\n'),
(46, '<div class="parrafo" align="justify">\r\nA veces detectamos que nuestra base de datos tiene un rendimiento muy bajo, esto se debe la mayoria de las veces a que hay queries muy pesadas que se estan ejecutando. Para saber que query esta ejecutando cada sesion podemos utilizar esta query.\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>	SQL>  select sesion.sid,\r\n		   sesion.username,\r\n		   optimizer_mode,\r\n		   hash_value,\r\n		   address,\r\n		   cpu_time,\r\n		   elapsed_time,\r\n		   sql_text\r\n	  from v$sqlarea sqlarea, v$session sesion\r\n	 where sesion.sql_hash_value = sqlarea.hash_value\r\n	   and sesion.sql_address    = sqlarea.address\r\n	   and sesion.username is not null;\r\n\r\n	Active session and the SQL it is executing\r\n	SID USERNAME   OPTIMIZER_MODE  HASH_VALUE ADDRESS    CPU_TIME ELAPSED_TIME\r\n	---- --------- --------------- ---------- -------- ---------- ------------\r\n	150 JKOOPMANN  ALL_ROWS        2803425422 6879D780   11923758     12106196\r\n\r\n	SQL_TEXT\r\n	--------------------------------------------------\r\n	select a.table_name from dba_tables a,dba_tables b\r\n</p></pre></blockquote>\r\n'),
(48, '<div class="parrafo" align="justify">\r\nEsta query nos presenta los diferentes indices que posee una tabla asi como las columnas que componen cada indice y la posicion que ocupan.\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>	SQL>  SET PAGES 10000\r\n	SET LINES 250\r\n	COL INDICE FORMAT A45\r\n	COL COLUMNA FORMAT A45\r\n	COL POSICION FORMAT A10\r\n\r\n	SELECT U1.INDEX_NAME INDICE, \r\n		   COLUMN_NAME COLUMNA,       \r\n		   SUBSTR(COLUMN_POSITION,1,50) POSICION\r\n	FROM USER_INDEXES U2, \r\n		 USER_IND_COLUMNS U1\r\n	WHERE U1.TABLE_NAME = ''&TABLA''\r\n	  AND U1.INDEX_NAME = U2.INDEX_NAME\r\n	ORDER BY U1.INDEX_NAME, \r\n			 COLUMN_POSITION ASC;\r\n\r\nEnter value for tabla: PPGA_PROMOACTPER\r\nold   6:        where u1.table_name = ''&tabla''\r\nnew   6:        where u1.table_name = ''PPGA_PROMOACTPER''\r\n\r\nINDICE                                        COLUMNA                                       POSICION\r\n--------------------------------------------- --------------------------------------------- ----------\r\nPK_PROMOACTPER                                COD_PROMOCION                                 1\r\nPK_PROMOACTPER                                COD_TIPACTPER                                 2\r\n			 \r\n</p></pre></blockquote>'),
(49, '<div class="parrafo" align="justify">\r\nPresento un script que utilizo para realizar el export de un listado de tablas presentes en un fichero. El cuerpo del script es muy sencillo, recibe 3 parametros: el due&ntilde;o del esquema (la password se pone a fuego dentro del script), el nombre del fichero de las tablas que se van a exportar y el path donde se van a dejar los ficheros de export.\r\n</div>\r\n<div class="parrafo" align="justify">\r\nSi alguna de las tablas del listado no existe, el procedimiento no termina con error unicamente deja constancia en el log (export_$fec.log). \r\n</div>\r\n<div class="parrafo" align="justify">\r\nEl resultado de este script es un tar con todos los export generados. Ademas de todos los parfile para hacer los import.\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif"><pre><p>\r\n#! /bin/ksh\r\n#---------------------------------------------------------------------------------------\r\n# Script: exportar_listado.ksh\r\n#\r\n# Parametros:\r\n#            Propietario esquema   \r\n#            Nombre del fichero donde estan las tablas   \r\n#			 Direccion donde se van a dejar export.\r\n#               \r\n# Fecha: 04/01/2012\r\n# Autor: lmds\r\n#---------------------------------------------------------------------------------------\r\n\r\nfec=`date +%Y%m%d_%H%M%S`\r\nFICH_LOG=export_$fec.log\r\n\r\n#--------------------------\r\n# Parametros de entrada\r\n#--------------------------\r\n\r\nnodo=$1\r\nlistado=$2\r\ndir_export=$3\r\n\r\nSQLPLUS=$ORACLE_HOME/bin/sqlplus; export SQLPLUS\r\nUSRPWD="$nodo/temporal"  export USRPWD\r\n\r\nrm -f /tmp/.exp*.tmp 2>/dev/null\r\nftmp=/tmp/.exp$$_${RANDOM}.tmp\r\n\r\n##---------------------------------------------------------------##\r\n## Function: LOG\r\n## Funcion que utilizamos para escribir las trazas.\r\n##---------------------------------------------------------------##\r\nfunction LOG {\r\n     fecha=`date +%H:%M:%S`\r\n     echo "[ $fecha ]    "$1 >> $FICH_LOG\r\n     echo "[ $fecha ]  "$1\r\n return 0\r\n}\r\n\r\n##---------------------------------------------------------------##\r\n## MAIN\r\n##---------------------------------------------------------------##\r\n\r\nif [ -s $listado ]\r\nthen\r\n	while read linea\r\n	do\r\n		tabla=`echo $linea|tr [a-z] [A-Z]`\r\n		LOG "-- TABLA: $tabla"\r\n		# Comprobamos si la tabla existe\r\n		\r\n		$SQLPLUS -s /nolog <<[EOSQL] > $ftmp\r\n		connect $USRPWD;\r\n		SELECT 1 FROM $tabla WHERE ROWNUM<2;		\r\n[EOSQL]\r\n		ca_err=`grep "^ORA-" $ftmp | wc -l`\r\n		if [ $ca_err -gt 0 ]; then\r\n		  LOG "-- ERROR $tabla NO existe"\r\n		  continue\r\n		fi\r\n		\r\n		#Construimos el fichero de parametros para el Export\r\n		\r\n		> expdp_parfile_${tabla}.txt\r\n		echo "userid=$nodo/temporal" >> expdp_parfile_${tabla}.txt\r\n		echo "directory=DIR_${tabla}" >> expdp_parfile_${tabla}.txt\r\n		echo "parallel=4" >> expdp_parfile_${tabla}.txt\r\n		echo "filesize=2G" >> expdp_parfile_${tabla}.txt\r\n		echo "dumpfile=export_full_${tabla}_%U.dmpx" >> expdp_parfile_${tabla}.txt\r\n		echo "logfile=export_$tabla.log" >> expdp_parfile_${tabla}.txt\r\n		echo "tables=$tabla" >> expdp_parfile_${tabla}.txt\r\n		echo "exclude=index,constraint" >> expdp_parfile_${tabla}.txt\r\n		LOG "Fichero: expdp_parfile_${tabla}.txt OK"\r\n\r\n		# Construimos el fichero de parametros para el Import\r\n\r\n		> impdp_parfile_${tabla}.txt\r\n		echo "userid=$nodo/temporal" >> impdp_parfile_${tabla}.txt\r\n		echo "directory=DIR_${tabla}" >> impdp_parfile_${tabla}.txt\r\n		echo "parallel=${paral_dp}" >> impdp_parfile_${tabla}.txt\r\n		echo "dumpfile=${tabla}_purgada_con_tabla_%U.dmpx" >> impdp_parfile_${tabla}.txt\r\n		echo "logfile=import_$tabla.log" >> impdp_parfile_${tabla}.txt\r\n		echo "tables=$tabla" >> impdp_parfile_${tabla}.txt\r\n		LOG "Fichero: impdp_parfile_${tabla}.txt OK"\r\n		\r\n		# Creamos el directorio\r\n		LOG "Creamos DIR_$tabla"\r\n		echo "CREATE OR REPLACE DIRECTORY DIR_$tabla AS ''$dir_export'';\r\n		GRANT READ, WRITE ON DIRECTORY DIR_$tabla  TO $nodo;\r\n		quit"|sqlplus -s "/ as sysdba"\r\n		\r\n[EOSQL]\r\n		ca_err=`grep "^ORA-" $ftmp | wc -l`\r\n		if [ $ca_err -gt 0 ]; then\r\n		  LOG "-- ERROR al crear el directorio DIR_$tabla"\r\n		fi\r\n		LOG " START export de $tabla"\r\n		expdp parfile=expdp_parfile_${tabla}.txt\r\n		[ $? -ne 0 ] && LOG "ERROR: Al ejecutar expdp parfile=expdp_parfile_${tabla}.txt" && exit 1\r\n		LOG " FINISH export terminado OK"\r\n			\r\n	done < $listado\r\nfi\r\nLOG "Generamos TAR"\r\n# Generamos un tar con todos los ficheros\r\ntar -cvf Import_params_$fec.tar impdp_parfile_*.tar\r\ncd $dir_export\r\ntar -cvf  Ficheros_export_$fec.tar *.dmpx 1> $FICH_LOG\r\n[ $? -ne 0 ] && LOG "--ERROR: al crear el tar" && exit 1\r\ngzip Ficheros_export_$fec.tar\r\nrm -f *.dmpx\r\nLOG "Procedimiento terminado OK"\r\n</p></pre></blockquote>'),
(50, '<div class="parrafo" align="justify">\r\nEste post utilizando un cursor y recorriendolo con un bucle for hacemos un drop de todos los indices de una tabla. Este script nos puede resultar util en el caso de que vayamos a realizar una carga masiva sobre una tabla, para de esta forma poder hacerla mas rapidamente y recrear los indices al final.\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>set serverout on lines 132 trimsp on\r\n	declare\r\n	 g_tab_name USER_TABLES.TABLE_NAME%type := ''&lt;MiTabla&gt;'';\r\n	 cursor CI is\r\n	  select INDEX_NAME\r\n	  from USER_INDEXES\r\n	  where table_name = g_tab_name;\r\n	begin\r\n	 for I in CI loop\r\n	  begin\r\n	   execute immediate ''drop index '' || I.INDEX_NAME;\r\n	  exception\r\n	   when others then\r\n		dbms_output.put_line( ''Error eliminando indice: '' || I.INDEX_NAME );\r\n		dbms_output.put_line( sqlerrm );\r\n	  end;\r\n	 end loop;\r\n	end;\r\n	/\r\n</p></pre></blockquote>'),
(51, '<div class="parrafo" align="justify">\r\nMuchas veces queremos recoger el resultado de una query en un fichero, para esta tarea podemos utilizar un spool.\r\n</div>\r\n<div class="parrafo" align="justify">\r\nSeguramente os haya ocurrido que lanzais una query bastante pesada y en mitad de la query se os corta la conexion. Para evitar eso suelo utilizar este script, que permite de una forma muy sencilla realizar un spool y lanzarlo con nohup en background.\r\n</div>\r\n<div class="parrafo" align="justify">\r\nPara utilizar este script unicamente teneis que editar las variables orausr, orapwd y fspool. Y en <AQUI VA LA ULTIMA QUERY DEL SPOOL> poneis la query de la que necesitais los datos.\r\n</div>\r\n\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>\r\n	# -----------------------------------------------------\r\n	# Script para hacer un SPOOL\r\n	# \r\n	# Auto: lmds\r\n	# \r\n	# Fecha: 2011/07/21  \r\n	# ------------------------------------------------------\r\n\r\n	# ------------------------------------------------------\r\n	# CONFIGURACION\r\n	# ------------------------------------------------------\r\n	orausr=&lt;Cambiar esto por el USER&gt;\r\n	orapwd=&lt;Cambiar esto por el PASS&gt;\r\n	fspool=&lt;Cambiar esto por el path donde se dejara los datos&gt;\r\n\r\n	[ -z "$ORACLE_HOME" ] && printf "ORACLE_HOME variable not defined" && exit 1\r\n	[ ! -d "$ORACLE_HOME" ] && printf "Directory $ORACLE_HOME doesn''t exist" && exit 1\r\n\r\n	printf "."\r\n\r\n	SQLPLUS=$ORACLE_HOME/bin/sqlplus; export SQLPLUS\r\n	[ ! -f $SQLPLUS ] && printf "The executable file for SQL*Plus  doesn''t exist" && exit 1\r\n	[ ! -x $SQLPLUS ] && printf "The current user can not execute SQL*Plus" && exit 1\r\n	[ -z "$ORACLE_SID" ] && printf "ORACLE_SID variable not defined" && exit 1\r\n\r\n	USRPWD=$orausr/$orapwd; export USRPWD\r\n\r\n	flog=spool_generico_`date ''+%Y%m%d_%H%M''`.log\r\n	ftmp=/tmp/.$$_${RANDOM}.tmp\r\n\r\n	# Comprobamos la conexion con la BD.\r\n\r\n	printf " Testing connection to ${ORA_SID} ..."\r\n\r\n	$SQLPLUS -s /nolog &lt;&lt;EOF &gt; $ftmp\r\n	connect $USRPWD;\r\n	select sysdate from dual;\r\n	exit\r\n	EOF\r\n\r\n	ca_err=`grep "^ORA-" $ftmp | wc -l`\r\n	[ $ca_err -gt 0 ] && printf "a Error connecting to ${ORA_SID} as ${orausr}: " && cat $ftmp  && exit 1\r\n	printf "OK"\r\n	printf "Iniciamos spool ["`date ''+%H:%M:%S''`"]" | tee -a $flog\r\n	$SQLPLUS -s /nolog <<[EOSQL] > $ftmp\r\n	connect $USRPWD;\r\n	set pages 0 line 1000 feedb off  trimsp on serverout on\r\n	spool $fspool\r\n	 &lt;AQUI VA LA ULTIMA QUERY DEL SPOOL&gt;\r\n	spool off\r\n	quit\r\n	[EOSQL]\r\n\r\n	ca_err=`grep "^ORA-" $ftmp | wc -l`\r\n\r\n	if [ $ca_err -gt 0 ]; then\r\n	 printf "Locate Oracle errors: " | tee -a $flog\r\n	 printf "---------------------------------- " | tee -a $flog\r\n	 cat $ftmp | tee -a $flog\r\n	 rm -f $ftmp\r\n	 exit 1\r\n	fi\r\n\r\n	printf "Spool terminado OK ["`date ''+%H:%M:%S''`"]" | tee -a $flog\r\n	printf "Registros exportados: "`wc -l $fspool`"" | tee -a $flog\r\n	rm -f $ftmp\r\n</p></pre></blockquote>'),
(52, '<h3>1. Elementos del lenguaje</h3>\r\n\r\n\r\n<div class="parrafo" align="justify">\r\nSe pueden clasificar en:\r\n<div class="parrafo_lista_sub">\r\na) Identificadores <br/>\r\nb) Literales<br/>\r\nc) Comentarios\r\n</div>\r\n</div>\r\n\r\n<div class="parrafo" align="justify">\r\nIdentificadores:\r\n<div class="parrafo_lista_sub">\r\n- Hasta 30 caracteres.<br/>\r\n- Deben de comenzar por un caracter alfabetico.<br/>\r\n- Pueden contener caracteres alfanumericos, $, _<br/>\r\n- No admite espacions.\r\n</div>\r\n</div>\r\n\r\n<div class="parrafo" align="justify">\r\n Literales y comentarios.\r\n<div class="parrafo_lista_sub">\r\nLos literales se delimitan por comillas simples.<br/>\r\nLos comentarios pueden estar en una linea o en varias.\r\n<div class="parrafo_lista_sub">\r\n- --Comentario de linea.<br/>\r\n- /* Comentario de mas de una linea */<br/>\r\n</div>\r\n</div>\r\n</div>\r\n<h3>\r\nBloques\r\n</h3>\r\n<div class="parrafo" align="justify">\r\nPLSQL trabaja mediante la definicion de bloque, estos pueden ser bloques anonimos o pueden tener nombre como es el caso de procedimientos, funciones o paquetes.\r\n</div>\r\n<div class="parrafo" align="justify">\r\nLa estructura de un bloque es:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>	DECLARE\r\n		&lt;Declaracion de variables&gt;\r\n	BEGIN\r\n		&lt;Cuerpo del bloque&gt;\r\n	EXCEPTION\r\n		&lt;Getion de excepciones&gt;\r\n	END;\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nEjemplo de bloque anonimo:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>	DECLARE\r\n	mi_variable NUMBER (5);\r\n	BEGIN\r\n	SELECT salario INTO mi_variable\r\n	FROM empleados\r\n	WHERE numero_empleado = 1234;\r\n	EXCEPTION\r\n	WHEN nombre_excepci&oacute;n THEN ...\r\n	END;\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nTipos de variables en Oracle:\r\n<div class="parrafo_lista_sub">\r\n&bull; Escalares:  s&oacute;lo pueden recoger un valor.<br/>\r\n&bull; Compuestas:  recogen fila o filas.<br/>\r\n&bull; Referencias: punteros que apuntan a objetos de otros programas.<br/>\r\n&bull; LOB (large objects): contienen localizadores que indican la localizaci&oacute;n de\r\nobjetos de gran tama&ntilde;o (por ejemplo im&aacute;genes).<br/>\r\n</div>\r\n</div>\r\n<div class="parrafo" align="justify">\r\nLas variables Escalares que admite PLSQL son:\r\n<div class="parrafo_lista_sub">\r\nCHAR [(longitud m&aacute;xima)]<br/>\r\nVARCHAR2 (longitud m&aacute;xima)<br/>\r\nNUMBER [(precisi&oacute;n, escala)]<br/>\r\nBINARY_INTEGER<br/>\r\nPLS_INTEGER<br/>\r\nBOOLEAN<br/>\r\nDATE\r\n</div>\r\n</div>\r\n\r\n<div class="parrafo" align="justify">\r\nEn el momento de la declaracion de la variable la podemos inicializar a un valor:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>DECLARE\r\n	v_contador	NUMBER :=5;\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nTambien si queremos declarar una variable que recoja el valor de una columna y no sabemos el tipo de esa columna podemos utilizar la clausula %TYPE.\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>DECLARE\r\n	v_id_empleado	EMPLEADOS.ID_EMPLEADO%type;\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nO en el caso de cursores podemos utilizar %ROWTYPE.\r\n</div>\r\n<div class="parrafo" align="justify">\r\nUtilizando el caracter & podemos hacer que Oracle pare la ejecucion del script y nos pida un valor que se le asignara a la variable.\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>v_tabla:=&tabla;\r\n\r\n</p></pre></blockquote>\r\n<h3>\r\nBloques anidados\r\n</h3>\r\n\r\n<div class="parrafo" align="justify">\r\nLa estructura anterior de bloque la podemos apliar utilizando bloques anidados. Podemos necesitar utilizar bloques anidados en el caso que queramos controlar una determinada excepcion si terminar la ejecucion del bloque o por el ambito de las variables.\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>DECLARE\r\n	&lt;declaracion variables padre&gt;\r\nBEGIN\r\n	&lt;sentencias 1&gt;\r\n	DECLARE\r\n		&lt;declaracion variables hijo&gt;\r\n	BEGIN\r\n		&lt;sentencias 2&gt;\r\n	EXCEPTION\r\n		-- Se tratan las excepciones generadas por &lt;sentencias 2&gt;\r\n	END;\r\nEXCEPTION\r\n	-- Se tratan las excepciones generadas en &lt;sentencias 1&gt; y las que no  se traten en &lt;sentencias 2&gt;\r\nEND;\r\n\r\n</p></pre></blockquote>\r\n\r\n<h3>\r\nInteraccion con la base de datos\r\n</h3>\r\n\r\n<div class="parrafo" align="justify">\r\nPodemos interactuar con la base de datos de varias maneras:\r\n</div>\r\n<div class="parrafo" align="justify">\r\n- Extrayendo datos:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>SELECT expresion INTO {var1[,var2] | registro } FROM nombre_tabla [WHERE condici&oacute;n];\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\n- Ejecucion de sentencias DML\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>execute immediate ''DROP ALL TABLES'';\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\n- Rollback y commit.\r\n</div>'),
(53, '<h3>\r\nIntroduccion\r\n</h3>\r\n<div class="parrafo" align="justify">\r\nTenemos que tener una serie de consideraciones previas respecto a las estructuras de control:\r\n</div>\r\n<div class="parrafo" align="justify">\r\n	-Los valores nulos (NULL) no se pueden evaluar siempre devuelven FALSE. Si que remos utilizarlos habra que utilizar las expresiones IS NULL o IS NOT NULL.\r\n</div>\r\n<div class="parrafo" align="justify">\r\n	- PLSQL es un lenguaje que no distingue entre mayusculas y minusculas.\r\n</div>\r\n<div class="parrafo" align="justify">\r\n	-Una variable no puede tener el mismo nombre que una columna de una tabla, es recomendable el aÃ±adir prefijos o nombrar el bloque y utilizar ese espacion de nombres.\r\n</div>\r\n<div class="parrafo" align="justify">\r\nEjemplo:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>&lt;&lt;Mibloque&gt;&gt;\r\nDECLARE\r\n	id_tabla 	NUMBER :=10;\r\nBEGIN\r\n	UPDATE tablas SET id_tabla=Mibloque.id_tabla;\r\nEND;\r\n/\r\n\r\n</p></pre></blockquote>\r\n<h3>1. IF</h3>\r\n\r\n<div class="parrafo" align="justify">\r\nEstructura condicional de sobra conocida. Estructuras que ofrece Oracle:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n	<pre><p>A) IF CONDICION THEN \r\n		&lt;sentencias&gt;\r\n	END IF;\r\n	\r\n	B) IF CONDICION THEN\r\n		&lt;sentencias&gt;\r\n	ELSE \r\n	&lt;sentencias&gt;\r\n	END IF;\r\n	\r\n	C)  IF CONDICION THEN\r\n		&lt;sentencias&gt;\r\n	ELSIF CONDICION2 THEN \r\n		&lt;sentencias&gt;\r\n	ELSE\r\n		&lt;sentencias&gt;\r\n	END IF;\r\n\r\n</p></pre></blockquote>\r\n<h3>\r\n2. CASE</h3>\r\n<div class="parrafo" align="justify">\r\nEjemplo:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n	<pre><p>CASE v_nota\r\n	WHEN 9 THEN V_calificacion : = ''Sobresaliente''\r\n	WHEN 7 THEN V_calificacion : = ''Notable''\r\n	WHEN 5 THEN V_calificacion : = ''Aprobado''\r\n	ELSE V_calificacion : = ''Suspenso''\r\n	END CASE;\r\n\r\n</p></pre></blockquote>\r\n<h3>3. BUCLES</h3>\r\n<div class="parrafo" align="justify">\r\n3.1 Bucle clasico\r\n</div>\r\n<div class="parrafo" align="justify">\r\nSe va ejecutando de forma indefinida hasta que forzamos la salida con EXIT.\r\n</div>\r\n<div class="parrafo" align="justify">\r\nEjemplo:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n	<pre><p>DECLARE\r\n	CONTADOR NUMBER(2):= 1;\r\n	BEGIN\r\n	LOOP\r\n	DBMS_OUTPUT.PUT_LINE(CONTADOR);\r\n	EXIT WHEN CONTADOR = 50;\r\n	CONTADOR := CONTADOR +1;\r\n	END LOOP;\r\n	END;\r\n	/\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nNOTA: EXIT WHEN permite establecer una sentencia de control en una unica linea.\r\n</div>\r\n<div class="parrafo" align="justify">\r\n3.2 Bucle WHILE\r\n</div>\r\n<div class="parrafo" align="justify">\r\nCon un bucle WHILE indicamos la condicion de salida.\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n	<pre><p>DECLARE\r\n	V_CONT NUMBER;\r\n	BEGIN\r\n	V_CONT :=0;\r\n	WHILE V_CONT&lt;50 LOOP\r\n	DBMS_OUTPUT.PUT_LINE(V_CONT);\r\n	V_CONT:=V_CONT + 1;\r\n	END LOOP;\r\n	END;\r\n	/\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\n3.3 Bucle FOR\r\n</div>\r\n<div class="parrafo" align="justify">\r\nE un bucle FOR indicamos un limite inferior y superior para el bucle. Utilizando la palabra REVERSE hacemos que vaya desde el limite superior al limite inferior. Dentro de un bucle FOR el contador no se puede modificar.\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif"\r\n	><pre><p>BEGIN\r\n	FOR I IN 1..50 LOOP\r\n	DBMS_OUTPUT.PUT_LINE(I);\r\n	END LOOP;\r\n	END;\r\n	/\r\n	BEGIN\r\n	FOR I IN REVERSE 1..50 LOOP\r\n	DBMS_OUTPUT.PUT_LINE(I);\r\n	END LOOP;\r\n	END;\r\n	/\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\n3.4 Etiquetar bloques.\r\n</div>\r\n<div class="parrafo" align="justify">\r\nCuando trabajamos con bucles anidados los podemos etiquetar, y generar secuencias de escape que provoquen la  salida de uno o de varios niveles.\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n	<pre><p>DECLARE\r\n		s PLS_INTEGER := 0;\r\n		i PLS_INTEGER := 0;\r\n		j PLS_INTEGER;\r\n	BEGIN\r\n	&lt;&lt;outer_loop&gt;&gt;\r\n	LOOP\r\n		i := i + 1;\r\n		j := 0;\r\n		&lt;&lt;inner_loop&gt;&gt;\r\n		LOOP\r\n			j := j + 1;\r\n			s := s + i * j; -- sum a bunch of products\r\n			EXIT inner_loop WHEN (j &gt; 5);\r\n			EXIT outer_loop WHEN ((i * j) &gt; 15);\r\n		END LOOP inner_loop;\r\n	END LOOP outer_loop;\r\n	DBMS_OUTPUT.PUT_LINE(''The sum of products equals: '' || TO_CHAR(s));\r\n	END;\r\n\r\n\r\n</p></pre></blockquote>\r\n<h3>\r\n4 GOTO</h3>\r\n<div class="parrafo" align="justify">\r\nDentro de un bloque nos permite saltar la linea de ejecucion a una determinada etiqueta.\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n	<pre><p>DECLARE\r\n		total NUMBER(9) := 0;\r\n		counter NUMBER(6) := 0;\r\n	BEGIN\r\n	&lt;&lt;calc_total&gt;&gt;\r\n		counter := counter + 1;\r\n		total := total + counter * counter;\r\n		-- branch to print_total label when condition is true\r\n		IF total &gt; 25000 THEN GOTO print_total;\r\n		ELSE GOTO calc_total;\r\n		END IF;\r\n		&lt;&lt;print_total&gt;&gt;\r\n		DBMS_OUTPUT.PUT_LINE(''Counter: '' || TO_CHAR(counter) || '' Total: '' ||\r\n		TO_CHAR(total));\r\n	END;\r\n	/\r\n\r\n</p></pre></blockquote>\r\n<h3>\r\n5 Ejemplos:</h3>\r\n<div class="parrafo" align="justify">\r\nEjemplo 1: combinaciones de estructuras de control.\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n	<pre><p>DECLARE\r\n		jobid employees.job_id%TYPE;\r\n		empid employees.employee_id%TYPE := 115;\r\n		sal employees.salary%TYPE;\r\n		sal_raise NUMBER(3,2);\r\n	BEGIN\r\n	SELECT job_id, salary INTO jobid, sal from employees WHERE employee_id = empid;\r\n	CASE\r\n	WHEN jobid = ''PU_CLERK'' THEN\r\n		IF sal &lt; 3000 THEN sal_raise := .12;\r\n		ELSE sal_raise := .09;\r\n		END IF;\r\n	WHEN jobid = ''SH_CLERK'' THEN\r\n		IF sal &lt; 4000 THEN sal_raise := .11;\r\n		ELSE sal_raise := .08;\r\n		END IF;\r\n	WHEN jobid = ''ST_CLERK'' THEN\r\n		IF sal &lt; 3500 THEN sal_raise := .10;\r\n		ELSE sal_raise := .07;\r\n		END IF;\r\n	ELSE\r\n		DBMS_OUTPUT.PUT_LINE(''No raise for this job: '' || jobid);\r\n	END CASE;\r\n	END;\r\n	/\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nEjemplo 2: Case que lanza un excepcion\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n	<pre><p>DECLARE\r\n	grade CHAR(1);\r\n	BEGIN\r\n	grade := ''B'';\r\n	CASE\r\n		WHEN grade = ''A'' THEN DBMS_OUTPUT.PUT_LINE(''Excellent'');\r\n		WHEN grade = ''B'' THEN DBMS_OUTPUT.PUT_LINE(''Very Good'');\r\n		WHEN grade = ''C'' THEN DBMS_OUTPUT.PUT_LINE(''Good'');    \r\n		ELSE RAISE CASE_NOT_FOUND;\r\n	END CASE;\r\n	EXCEPTION\r\n	 WHEN CASE_NOT_FOUND THEN\r\n	 DBMS_OUTPUT.PUT_LINE(''No such grade'');\r\n	 END;\r\n	/\r\n\r\n</p></pre></blockquote>\r\n\r\n');
INSERT INTO `ENTRADA_TEXTO` (`ID_ENTRADA`, `TEXTO`) VALUES
(54, '<h3>\r\n1. Tipos de Collections:\r\n</h3>\r\n\r\n<div class="parrafo" align="justify">\r\na) Nested tables: Podemos pensar en un array de valores sin tener que declarar su longitud previamente. Podemos generar nested tables multidimensionales haciendo nested tables de nested tables. \r\n</div>\r\n<div class="parrafo" align="justify">\r\nb) Varrays: Permite acceder a sus  elementos de forma individual o trabajar con el array como si fuese un todo. Un varray tiene un tama&ntilde;o maximo que se debe especificar en su declaracion.\r\n</div>\r\n<div class="parrafo" align="justify">\r\nc) Arrays asociativos: Los podemos entender como un array compuesto por duplas llave - valor.\r\n</div>\r\n<div class="parrafo" align="justify">\r\nEjemplo de collection:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>DECLARE\r\n    TYPE population_type IS TABLE OF NUMBER INDEX BY VARCHAR2(64);\r\n    country_population population_type;\r\n    continent_population population_type;\r\n    howmany NUMBER;\r\n    which VARCHAR2(64);\r\nBEGIN\r\n    country_population(''Greenland'') := 100000; -- Nueva entrada\r\n    country_population(''Iceland'') := 750000; -- Nueva entrada\r\n-- Obtenemos el valor asociado a una entrada\r\n    howmany := country_population(''Greenland'');\r\n    continent_population(''Australia'') := 30000000;\r\n    continent_population(''Antarctica'') := 1000; -- Nueva entrada\r\n    continent_population(''Antarctica'') := 1001; -- Modificamos valor\r\n-- .FIRST devuelve en orden alfabetico\r\n    which := continent_population.FIRST;\r\n    which := continent_population.LAST;\r\n    howmany := continent_population(continent_population.LAST);\r\nEND;\r\n/\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nPara crear una coleccion primero debemos de  definir un tipo y despues declarar variables de ese tipo.\r\n</div>\r\n<div class="parrafo" align="justify">\r\nPara un Varray seria:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>TYPE Calendario IS VARRAY(366) OF DATE;\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nPara un array asociativo:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>TYPE EmpTabTyp IS TABLE OF employees%ROWTYPE INDEX BY PLS_INTEGER;\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nPara una nested table:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>TYPE nested_type IS TABLE OF VARCHAR2(30);\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nUn ejemplo seria:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>DECLARE\r\n    TYPE nested_type IS TABLE OF VARCHAR2(30);\r\n    TYPE varray_type IS VARRAY(5) OF INTEGER;\r\n    TYPE assoc_array_num_type IS TABLE OF NUMBER INDEX BY PLS_INTEGER;\r\n    TYPE assoc_array_str_type IS TABLE OF VARCHAR2(32) INDEX BY PLS_INTEGER;\r\n    TYPE assoc_array_str_type2 IS TABLE OF VARCHAR2(32) INDEX BY VARCHAR2(64);\r\n    v1 nested_type;\r\n    v2 varray_type;\r\n    v3 assoc_array_num_type;\r\n    v4 assoc_array_str_type;\r\n    v5 assoc_array_str_type2;\r\nBEGIN\r\n    v1 := nested_type(''Shipping'',''Sales'',''Finance'',''Payroll'');\r\n    v2 := varray_type(1, 2, 3, 4, 5); -- Up to 5 integers\r\n    v3(99) := 10; -- Just start assigning to elements\r\n    v3(7) := 100; -- Subscripts can be any integer values\r\n    v4(42) := ''Smith''; -- Just start assigning to elements\r\n    v4(54) := ''Jones''; -- Subscripts can be any integer values\r\n    v5(''Canada'') := ''North America''; -- Just start assigning to elements\r\n    v5(''Greece'') := ''Europe''; -- Subscripts can be string values\r\nEND;\r\n/\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nPodemos hacer un Varray de records\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>DECLARE\r\nTYPE name_rec IS RECORD ( first_name VARCHAR2(20), last_name VARCHAR2(25) );\r\nTYPE names IS VARRAY(250) OF name_rec;\r\nBEGIN\r\nNULL;\r\nEND;\r\n/\r\n\r\n</p></pre></blockquote>\r\n<h3>\r\n2. Inicializar collections\r\n</h3>\r\n<div class="parrafo" align="justify">\r\nPara introducir elementos a una coleccion debemos de llamar a su constructor:\r\n</div>\r\n<div class="parrafo" align="justify">\r\nPara un varray:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>DECLARE\r\nTYPE dnames_var IS VARRAY(20) OF VARCHAR2(30);\r\ndept_names dnames_var;\r\nBEGIN\r\ndept_names := dnames_var(''Shipping'',''Sales'',''Finance'',''Payroll'');\r\nEND;\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nPara una nested table:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>DECLARE\r\n	TYPE dnames_tab IS TABLE OF VARCHAR2(30);\r\n	dept_names dnames_tab;\r\nBEGIN\r\n	dept_names := dnames_tab(''Shipping'', NULL,''Finance'', NULL);\r\nEND;\r\n\r\n</p></pre></blockquote>\r\n<h3>\r\n3. Referenciar Objetos\r\n</h3>\r\n<div class="parrafo" align="justify">\r\nPara una nested table:\r\n</div>\r\n<div class="parrafo" align="justify">\r\nPara acceder a un determinado elemento seria nombre_variable(id_elemento)\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>DECLARE\r\n	TYPE Roster IS TABLE OF VARCHAR2(15);\r\n	names Roster := Roster(''D Caruso'', ''J Hamil'', ''D Piro'', ''R Singh'');\r\n	PROCEDURE verify_name(the_name VARCHAR2) IS\r\n	BEGIN\r\n		DBMS_OUTPUT.PUT_LINE(the_name);\r\n	END;\r\nBEGIN\r\n	FOR i IN names.FIRST .. names.LAST\r\n	LOOP\r\n		IF names(i) = ''J Hamil'' THEN\r\n			DBMS_OUTPUT.PUT_LINE(names(i)); -- reference to nested table element\r\n		END IF;\r\n	END LOOP;\r\n	verify_name(names(3)); -- procedure call with reference to element\r\nEND;\r\n/\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nPara array asociativos:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>DECLARE\r\n	TYPE sum_multiples IS TABLE OF PLS_INTEGER INDEX BY PLS_INTEGER;\r\n	n PLS_INTEGER := 5; -- number of multiples to sum for display\r\n	sn PLS_INTEGER := 10; -- number of multiples to sum\r\n	m PLS_INTEGER := 3; -- multiple\r\n\r\nFUNCTION get_sum_multiples(multiple IN PLS_INTEGER, num IN PLS_INTEGER)\r\n	RETURN sum_multiples IS s sum_multiples;\r\n	BEGIN\r\n	FOR i IN 1..num LOOP\r\n		s(i) := multiple * ((i * (i + 1)) / 2) ; -- sum of multiples\r\n	END LOOP;\r\n	RETURN s;\r\nEND get_sum_multiples;\r\nBEGIN\r\n	-- call function to retrieve the element identified by subscript (key)\r\n	DBMS_OUTPUT.PUT_LINE(''Sum of the first '' || TO_CHAR(n) || '' multiples of '' ||\r\n	TO_CHAR(m) || '' is '' || TO_CHAR(get_sum_multiples (m, sn)(n)));\r\nEND;\r\n/\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nOperar con colecciones en bloque:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>DECLARE\r\n	TYPE nested_typ IS TABLE OF NUMBER;\r\n	nt1 nested_typ := nested_typ(1,2,3);\r\n	nt2 nested_typ := nested_typ(3,2,1);\r\n	nt3 nested_typ := nested_typ(2,3,1,3);\r\n	nt4 nested_typ := nested_typ(1,2,4);\r\nanswer nested_typ;\r\n\r\nPROCEDURE print_nested_table(the_nt nested_typ) IS output VARCHAR2(<div class="parrafo" align="justify">8);\r\nBEGIN\r\n	IF the_nt IS NULL THEN\r\n	DBMS_OUTPUT.PUT_LINE(''Results: &lt;NULL&gt;'');\r\n	RETURN;\r\nEND IF;\r\nIF the_nt.COUNT = 0 THEN\r\nDBMS_OUTPUT.PUT_LINE(''Results: empty set'');\r\nRETURN;\r\nEND IF;\r\nFOR i IN the_nt.FIRST .. the_nt.LAST\r\nLOOP\r\noutput := output || the_nt(i) || '' '';\r\nEND LOOP;\r\nDBMS_OUTPUT.PUT_LINE(''Results: '' || output);\r\nEND;\r\nBEGIN\r\n	answer := nt1 MULTISET UNION nt4; -- (1,2,3,1,2,4)\r\n	print_nested_table(answer);\r\n	answer := nt1 MULTISET UNION nt3; -- (1,2,3,2,3,1,3)\r\n	print_nested_table(answer);\r\n	answer := nt1 MULTISET UNION DISTINCT nt3; -- (1,2,3)\r\n	print_nested_table(answer);\r\n	answer := nt2 MULTISET INTERSECT nt3; -- (3,2,1)\r\n	print_nested_table(answer);\r\n	answer := nt2 MULTISET INTERSECT DISTINCT nt3; -- (3,2,1)\r\n	print_nested_table(answer);\r\n	answer := SET(nt3); -- (2,3,1)\r\n	print_nested_table(answer);\r\n	answer := nt3 MULTISET EXCEPT nt2; -- (3)\r\n	print_nested_table(answer);\r\n	answer := nt3 MULTISET EXCEPT DISTINCT nt2; -- ()\r\n	print_nested_table(answer);\r\nEND;\r\n	\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nPodemos hacer operaciones con collections como si fuesen un unico objeto.\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>DECLARE\r\n    TYPE nested_typ IS TABLE OF NUMBER;\r\n    nt1 nested_typ := nested_typ(1,2,3);\r\n    nt2 nested_typ := nested_typ(3,2,1);\r\n    nt3 nested_typ := nested_typ(2,3,1,3);\r\n    nt4 nested_typ := nested_typ(1,2,4);\r\n    answer BOOLEAN;\r\n    howmany NUMBER;\r\n    PROCEDURE testify(truth BOOLEAN DEFAULT NULL, quantity NUMBER DEFAULT NULL) IS\r\n    BEGIN\r\n   	 IF truth IS NOT NULL THEN\r\n   		 DBMS_OUTPUT.PUT_LINE(CASE truth WHEN TRUE THEN ''True'' WHEN FALSE THEN ''False'' END);\r\n   	 END IF;\r\n   	 IF quantity IS NOT NULL THEN\r\n   		 DBMS_OUTPUT.PUT_LINE(quantity);\r\n   	 END IF;\r\n    END;\r\nBEGIN\r\n    answer := nt1 IN (nt2,nt3,nt4); -- true, nt1 matches nt2\r\n    testify(truth =&gt; answer);\r\n    answer := nt1 SUBMULTISET OF nt3; -- true, all elements match\r\n    testify(truth =&gt; answer);\r\n    answer := nt1 NOT SUBMULTISET OF nt4; -- also true\r\n    testify(truth =&gt; answer);\r\n    howmany := CARDINALITY(nt3); -- number of elements in nt3\r\n    testify(quantity =&gt; howmany);\r\n    howmany := CARDINALITY(SET(nt3)); -- number of distinct elements\r\n    testify(quantity =&gt; howmany);\r\n    answer := 4 MEMBER OF nt1; -- false, no element matches\r\n    testify(truth =&gt; answer);\r\n    answer := nt3 IS A SET; -- false, nt3 has duplicates\r\n    testify(truth =&gt; answer);\r\n    answer := nt3 IS NOT A SET; -- true, nt3 has duplicates\r\n    testify(truth =&gt; answer);\r\n    answer := nt1 IS EMPTY; -- false, nt1 has some members\r\n    testify(truth =&gt; answer);\r\nEND;\r\n/\r\n</p></pre></blockquote>\r\n<h3>\r\n4. Metodos para trabajar con colecciones\r\n</h3>\r\n<div class="parrafo" align="justify">\r\nEXISTS(N) devuelve TRUE si el elemenot N existe&lt;/br&gt;. </br>\r\nDELETE(N) elimina, el elemento N de la coleccion.\r\n</div>\r\n<div class="parrafo" align="justify">\r\nEjemplo:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>DECLARE\r\nTYPE NumList IS TABLE OF INTEGER;\r\nn NumList := NumList(1,3,5,7);\r\nBEGIN\r\nn.DELETE(2); -- Delete the second element\r\nIF n.EXISTS(1) THEN\r\nDBMS_OUTPUT.PUT_LINE(''OK, element #1 exists.'');\r\nEND IF;\r\nIF n.EXISTS(2) = FALSE THEN\r\nDBMS_OUTPUT.PUT_LINE(''OK, element #2 has been deleted.'');\r\nEND IF;\r\nIF n.EXISTS(99) = FALSE THEN\r\nDBMS_OUTPUT.PUT_LINE(''OK, element #99 does not exist at all.'');\r\nEND IF;\r\nEND;\r\n/\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nCOUNT cuenta el numero de elementos que tiene la coleccion.&lt;/br&gt;</br>\r\nEXTEND(n), TRIM(n) incrementa o decrementa el tama&ntilde;o de la coleccion, inserta elementos nulos.\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>DECLARE\r\nTYPE NumList IS TABLE OF NUMBER;\r\nn NumList := NumList(2,4,6,8); -- Collection starts with 4 elements.\r\nBEGIN\r\nDBMS_OUTPUT.PUT_LINE(''There are '' || n.COUNT || '' elements in N.'');\r\nn.EXTEND(3); -- Add 3 new elements at the end.\r\nDBMS_OUTPUT.PUT_LINE(''Now there are '' || n.COUNT || '' elements in N.'');\r\nn := NumList(86,99); -- Assign a completely new value with 2 elements.\r\nDBMS_OUTPUT.PUT_LINE(''Now there are '' || n.COUNT || '' elements in N.'');\r\nn.TRIM(2); -- Remove the last 2 elements, leaving none.\r\nDBMS_OUTPUT.PUT_LINE(''Now there are '' || n.COUNT || '' elements in N.'');\r\nEND;\r\n/\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nFIRST, LAST devuelve el primer y ultimo elemento de la conexion\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>DECLARE\r\n    TYPE NumList IS TABLE OF NUMBER;\r\n    n NumList := NumList(1,3,5,7);\r\n    counter INTEGER;\r\nBEGIN\r\n    DBMS_OUTPUT.PUT_LINE(''N''''s first subscript is '' || n.FIRST);\r\n    DBMS_OUTPUT.PUT_LINE(''N''''s last subscript is '' || n.LAST);\r\n    -- When the subscripts are consecutive starting at 1,\r\n    -- it''s simple to loop through them.\r\n    FOR i IN n.FIRST .. n.LAST\r\n    LOOP\r\n    DBMS_OUTPUT.PUT_LINE(''Element #'' || i || '' = '' || n(i));\r\n    END LOOP;\r\n    n.DELETE(2); -- Delete second element.\r\n    -- When the subscripts have gaps or the collection might be uninitialized,\r\n    -- the loop logic is more extensive. We start at the first element, and\r\n    -- keep looking for the next element until there are no more.\r\n    IF n IS NOT NULL THEN\r\n    counter := n.FIRST;\r\n    WHILE counter IS NOT NULL\r\n    LOOP\r\n    DBMS_OUTPUT.PUT_LINE(''Element #'' || counter || '' = '' || n(counter));\r\n    counter := n.NEXT(counter);\r\n    END LOOP;\r\n    ELSE\r\n    DBMS_OUTPUT.PUT_LINE(''N is null, nothing to do.'');\r\n    END IF;\r\nEND;\r\n/\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nPRIOR(n), NEXT(n) Para recorrer una coleccion utiliamos estos procedimientos.\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>DECLARE\r\nTYPE NumList IS TABLE OF NUMBER;\r\nn NumList := NumList(1966,1971,1984,1989,1999);\r\nBEGIN\r\n	DBMS_OUTPUT.PUT_LINE(''The element after #2 is #'' || n.NEXT(2));\r\n	DBMS_OUTPUT.PUT_LINE(''The element before #2 is #'' || n.PRIOR(2));\r\n	n.DELETE(3); -- Delete an element to show how NEXT can handle gaps.\r\n	DBMS_OUTPUT.PUT_LINE(''Now the element after #2 is #'' || n.NEXT(2));\r\n	IF n.PRIOR(n.FIRST) IS NULL THEN\r\n		DBMS_OUTPUT.PUT_LINE(''Can''''t get PRIOR of the first element or NEXT of the\r\n	last.'');\r\n	END IF;\r\nEND;\r\n/\r\nDECLARE\r\n    TYPE NumList IS TABLE OF NUMBER;\r\n    n NumList := NumList(1,3,5,7);\r\n    counter INTEGER;\r\nBEGIN\r\n    n.DELETE(2); -- Delete second element.\r\n    -- When the subscripts have gaps, the loop logic is more extensive. We start at\r\n    -- the first element, and keep looking for the next element until there are no\r\n    more.\r\n    counter := n.FIRST;\r\n    WHILE counter IS NOT NULL\r\n    LOOP\r\n   	 DBMS_OUTPUT.PUT_LINE(''Counting up: Element #'' || counter || '' = '' ||n(counter));\r\n   	 counter := n.NEXT(counter);\r\n    END LOOP;\r\n    -- Run the same loop in reverse order.\r\n    counter := n.LAST;\r\n    WHILE counter IS NOT NULL\r\n    LOOP\r\n    DBMS_OUTPUT.PUT_LINE(''Counting down: Element #'' || counter || '' = '' ||n(counter));\r\n    counter := n.PRIOR(counter);\r\n    END LOOP;\r\nEND;\r\n/\r\n\r\n</p></pre></blockquote>\r\n<h3>\r\nManejo de excepciones\r\n</h3>\r\n<div class="parrafo" align="justify">\r\nLas excepciones que obtenemos al trabajar con colecciones:\r\n<div class="parrafo_lista_sub">\r\n- COLLECTION_IS_NULL: la coleccion no tiene elementos.</br>\r\n- NO_DATA_FOUND: el elemento al que se intenta acceder no existe.</br>\r\n- SUBSCRIPT_BEYOND_COUNT: se excede el numero maximo de elementos de una coleccion.\r\n</div>\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>DECLARE\r\n    TYPE WordList IS TABLE OF VARCHAR2(5);\r\n    words WordList;\r\n    err_msg VARCHAR2(100);\r\n    PROCEDURE display_error IS\r\n    BEGIN\r\n   	 err_msg := SUBSTR(SQLERRM, 1, 100);\r\n   	 DBMS_OUTPUT.PUT_LINE(''Error message = '' || err_msg);\r\n    END;\r\nBEGIN\r\n    BEGIN\r\n   	 words(1) := 10; -- Raises COLLECTION_IS_NULL\r\n   	 -- A constructor has not been used yet.\r\n   	 -- Note: This exception applies to varrays and nested tables,\r\n   	 -- but not to associative arrays which do not need a constructor.\r\n    EXCEPTION\r\n   	 WHEN OTHERS THEN display_error;\r\n    END;\r\n    -- After using a constructor, we can assign values to the elements.\r\n    words := WordList(''1st'', ''2nd'', ''3rd''); -- 3 elements created\r\n    -- Any expression that returns a VARCHAR2(5) is valid.\r\n    words(3) := words(1) || ''+2'';\r\n    BEGIN\r\n   	 words(3) := ''longer than 5 characters''; -- Raises VALUE_ERROR\r\n   	 -- The assigned value is too long.\r\n    EXCEPTION\r\n   	 WHEN OTHERS THEN display_error;\r\n    END;\r\n    BEGIN\r\n   	 words(''B'') := ''dunno''; -- Raises VALUE_ERROR\r\n   	 -- The subscript (B) of a nested table must be an integer.\r\n   	 -- Note: Also, NULL is not allowed as a subscript.\r\n    EXCEPTION\r\n   	 WHEN OTHERS THEN display_error;\r\n    END;\r\n    BEGIN\r\n   	 words(0) := ''zero''; -- Raises SUBSCRIPT_OUTSIDE_LIMIT\r\n   	 -- Subscript 0 is outside the allowed subscript range.\r\n    EXCEPTION\r\n    WHEN OTHERS THEN display_error;\r\n    END;\r\n    BEGIN\r\n   	 words(4) := ''maybe''; -- Raises SUBSCRIPT_BEYOND_COUNT\r\n   	 -- The subscript (4) exceeds the number of elements in the table.\r\n   	 -- To add new elements, call the EXTEND method first.\r\n    EXCEPTION\r\n   	 WHEN OTHERS THEN display_error;\r\n    END;\r\n    BEGIN\r\n   	 words.DELETE(1);\r\n   	 IF words(1) = ''First'' THEN NULL; END IF; -- Raises NO_DATA_FOUND\r\n   	 -- The element with subcript (1) has been deleted.\r\n    EXCEPTION\r\n   	 WHEN OTHERS THEN display_error;\r\n    END;\r\nEND;\r\n/\r\n</p></pre></blockquote>\r\n'),
(55, '<div class="parrafo" align="justify">\r\n    PL/SQL nos permite leer varios registros en una tabla de PL con un &uacute;nico acceso a trav&eacute;s de la instrucci&oacute;n BULK COLLECT.\r\n</div>\r\n<div class="parrafo" align="justify">\r\n    Esto nos permitir&aacute; reducir el n&uacute;mero de accesos a disco, por lo que optimizaremos el rendimiento de nuestras aplicaciones. Como contrapartida el consumo de memoria ser&aacute; mayor.\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>DECLARE\r\n   TYPE t_descripcion IS TABLE OF PAISES.DESCRIPCION%TYPE;\r\n   TYPE t_continente  IS TABLE OF PAISES.CONTINENTE%TYPE;\r\n   v_descripcion t_descripcion;\r\n   v_continente  t_continente;\r\n BEGIN\r\n   SELECT DESCRIPCION, \r\n          CONTINENTE\r\n   BULK COLLECT INTO v_descripcion, v_continente \r\n   FROM PAISES;\r\n   FOR i IN v_descripcion.FIRST .. v_descripcion.LAST LOOP\r\n     dbms_output.put_line(v_descripcion(i) || '', '' || v_continente(i));\r\n   END LOOP;\r\n END;\r\n /\r\n </p></pre></blockquote>\r\n <div class="parrafo" align="justify">\r\n    Podemos utilizar BULK COLLECT con registros de PL.\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p> DECLARE\r\n   TYPE PAIS IS RECORD (CO_PAIS     NUMBER  ,\r\n         		DESCRIPCION VARCHAR2(50),\r\n         		CONTINENTE  VARCHAR2(20)); \r\n   TYPE t_paises IS TABLE OF PAIS;\r\n   v_paises t_paises;\r\n BEGIN\r\n   SELECT  CO_PAIS, DESCRIPCION, CONTINENTE\r\n   BULK COLLECT INTO v_paises\r\n   FROM PAISES;\r\n   FOR i IN v_paises.FIRST .. v_paises.LAST LOOP\r\n     dbms_output.put_line(v_paises(i).DESCRIPCION || '', '' || v_paises(i).CONTINENTE);\r\n   END LOOP;\r\n\r\n END;\r\n /\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">  \r\n  Tambien podemos utilizar el atributo ROWTYPE.\r\n</div>\r\n\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p> DECLARE\r\n    TYPE t_paises IS TABLE OF PAISES%ROWTYPE;\r\n	v_paises t_paises;\r\n BEGIN\r\n   SELECT  CO_PAIS, DESCRIPCION, CONTINENTE\r\n   BULK COLLECT INTO v_paises\r\n   FROM PAISES;\r\n  \r\n   FOR i IN v_paises.FIRST .. v_paises.LAST LOOP\r\n     dbms_output.put_line(v_paises(i).DESCRIPCION ||'', '' || v_paises(i).CONTINENTE);\r\n   END LOOP;\r\n\r\n END;\r\n /\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify"> \r\n La cl&aacute;usula LIMIT nos permite definir la cantidad de datos que vamos a colocar en memoria.\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>DECLARE\r\n    TYPE t_paises IS TABLE OF PAISES%ROWTYPE;\r\n	v_paises t_paises;\r\n    CURSOR cur_paises is\r\n		SELECT  CO_PAIS, DESCRIPCION, CONTINENTE;\r\n BEGIN\r\n   OPEN cur_paises\r\n   LOOP \r\n   FETCH cur_paises BULK COLLECT INTO v_paises LIMIT 100;\r\n     FOR i IN 1 .. v_paises.COUNT\r\n     LOOP\r\n       dbms_output.put_line(v_paises(i).DESCRIPCION || \r\n  					'', '' || v_paises(i).CONTINENTE);\r\n     END LOOP;\r\n   END LOOP;\r\n END;\r\n /\r\n \r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nMientras mas peque&ntilde;o en valor sera menos costoso en memoria.\r\n</div>'),
(56, '<div class="parrafo" align="justify">\r\nPodemos considerar a un record como un objeto que puede almacenar otros objetos de diferentes tipos.\r\n</div>\r\n<h3>Ejemplo 1:</h3>\r\n\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>DECLARE\r\n	TYPE DeptRecTyp IS RECORD (\r\n		deptid NUMBER(4) NOT NULL := 99,\r\n		dname departments.department_name%TYPE,\r\n		loc departments.location_id%TYPE,\r\n		region regions%ROWTYPE );\r\n	dept_rec DeptRecTyp;\r\nBEGIN\r\n	dept_rec.dname := ''PURCHASING'';\r\nEND;\r\n/\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nEl ejemplo 1 muestra como se declara e inicializa un record en la seccion de DECLARE y como se le pueden asignar objetos en la seccion de BEGIN.\r\n</div>\r\n<h3>Ejemplo 2:</h3>\r\n\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>DECLARE\r\n	TYPE timerec IS RECORD (hours SMALLINT, minutes SMALLINT);\r\n	TYPE meetin_typ IS RECORD (\r\n		date_held DATE,\r\n		duration timerec, -- nested record\r\n		location VARCHAR2(20),\r\n		purpose VARCHAR2(50));\r\nBEGIN\r\n	NULL;\r\nEND;\r\n/\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nEn el ejemplo podemos ver ademas de como se define un record, la posibilidad de crear records anidados.\r\n</div>\r\n<h3>Ejemplo 3:</h3>\r\n\r\n\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>DECLARE\r\n	TYPE EmpRecTyp IS RECORD (\r\n		emp_id NUMBER(6),\r\n		salary NUMBER(8,2));\r\n	CURSOR desc_salary RETURN EmpRecTyp IS\r\n		SELECT employee_id, salary FROM employees ORDER BY salary DESC;\r\n	emp_rec EmpRecTyp;\r\n	FUNCTION nth_highest_salary (n INTEGER) RETURN EmpRecTyp IS\r\n	BEGIN\r\n		OPEN desc_salary;\r\n		FOR i IN 1..n LOOP\r\n			FETCH desc_salary INTO emp_rec;\r\n		END LOOP;\r\n		CLOSE desc_salary;\r\n	RETURN emp_rec;\r\n	END nth_highest_salary;\r\nBEGIN\r\n	NULL;\r\nEND;\r\n/\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nEjemplo que muestra como un procedimiento puede devolver un objeto de tipo record.\r\n</div>\r\n<h3>Ejemplo 4:</h3>\r\n\r\n\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>DECLARE\r\n	TYPE EmpRecTyp IS RECORD (\r\n		emp_id NUMBER(6),\r\n		emp_sal NUMBER(8,2) );\r\n	PROCEDURE raise_salary (emp_info EmpRecTyp) IS\r\n	BEGIN\r\n		UPDATE employees SET salary = salary + salary * .10\r\n			WHERE employee_id = emp_info.emp_id;\r\n	END raise_salary;\r\nBEGIN\r\n	NULL;\r\nEND;\r\n/\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nComo podemos pasar por parametro un record a un procedimiento.\r\n</div>\r\n<h3>Ejemplo 5:</h3>\r\n\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>DECLARE\r\n	-- Two identical type declarations.\r\n	TYPE DeptRec1 IS RECORD ( dept_num NUMBER(2), dept_name VARCHAR2(14));\r\n	TYPE DeptRec2 IS RECORD ( dept_num NUMBER(2), dept_name VARCHAR2(14));\r\n	dept1_info DeptRec1;\r\n	dept2_info DeptRec2;\r\n	dept3_info DeptRec2;\r\nBEGIN\r\n	-- ERROR No se pueden igualar dos records con diferentes tipos\r\n	-- dept1_info := dept2_info;\r\n	-- Si se pueden igualar\r\n	dept2_info := dept3_info;\r\nEND;\r\n/\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nPermite trabajar con registros como un unico objeto.\r\n</div>\r\n<h3>Ejemplo 6:</h3>\r\n\r\n\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>DECLARE\r\n    TYPE RecordTyp IS RECORD (last employees.last_name%TYPE,\r\n   	 id employees.employee_id%TYPE);\r\n   	 rec1 RecordTyp;\r\nBEGIN\r\n    SELECT last_name, employee_id INTO rec1 FROM employees WHERE ROWNUM &lt; 2;\r\n    DBMS_OUTPUT.PUT_LINE(''Employee #'' || rec1.id || '' = '' || rec1.last);\r\nEND;\r\n/\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nEl ejemplo 6 muestra como se puede utilizar un record dentro de una sentencia SELECT INTO.\r\n</div>\r\n<h3>Ejemplo 7:</h3>\r\n\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>DECLARE\r\n    dept_info departments%ROWTYPE;\r\nBEGIN\r\ndept_info.department_id := 300;\r\ndept_info.department_name := ''Personnel'';\r\ndept_info.location_id := 1700;\r\nINSERT INTO departments VALUES dept_info;\r\nUPDATE departments SET ROW = dept_info WHERE department_id = 300;\r\nEND;\r\n/\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nEn este ejemplo vemos un record implicito al utilizar la sentencia %ROWTYPE. Tb podemos ver en la sencencia update, como podemos modificar toda la fila utilizando el parametro ROW.\r\n</div>\r\n<h3>Ejemplo 8:</h3>\r\n\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>DECLARE\r\n    TYPE EmployeeSet IS TABLE OF employees%ROWTYPE;\r\n    underpaid EmployeeSet;\r\n    CURSOR c1 IS SELECT first_name, last_name FROM employees;\r\n    TYPE NameSet IS TABLE OF c1%ROWTYPE;\r\n    some_names NameSet;\r\nBEGIN\r\n\r\nSELECT * BULK COLLECT INTO underpaid FROM employees\r\n    WHERE salary &lt; 5000 ORDER BY salary DESC;\r\nDBMS_OUTPUT.PUT_LINE(underpaid.COUNT || '' people make less than 5000.'');\r\nFOR i IN underpaid.FIRST .. underpaid.LAST\r\nLOOP\r\n    DBMS_OUTPUT.PUT_LINE(underpaid(i).last_name || '' makes '' ||underpaid(i).salary);\r\nEND LOOP;\r\nSELECT first_name, last_name BULK COLLECT INTO some_names FROM employees\r\nWHERE ROWNUM &lt; 11;\r\nFOR i IN some_names.FIRST .. some_names.LAST\r\nLOOP\r\n    DBMS_OUTPUT.PUT_LINE(''Employee = '' || some_names(i).first_name || '' '' ||some_names(i).last_name);\r\nEND LOOP;\r\nEND;\r\n/\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nEl ejemplo 8 muestra como utilizando la senecia BULK COLLECT en una estructura SELECT INTO podemos asignar varias filas a un RECORD.\r\n</div>'),
(57, '<h3>Ejemplo 1:</h3>\r\n\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>BEGIN\r\n	UPDATE employees_temp SET salary = salary * 1.05 WHERE salary &lt; 5000;\r\n	DBMS_OUTPUT.PUT_LINE(''Updated '' || SQL%ROWCOUNT || '' salaries.'');\r\nEND;\r\n/\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nCon SQL%ROWCOUNT obtenemos el numero de registros que se han actualizado.\r\n</div>\r\n<h3>Ejemplo 2:</h3>\r\n\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>CREATE TABLE employees_temp AS SELECT first_name, last_name FROM employees;\r\nDECLARE\r\n	x VARCHAR2(20) := ''my_first_name'';\r\n	y VARCHAR2(25) := ''my_last_name'';\r\n	v_table VARCHAR2(25) := ''MiTabla'';\r\nBEGIN\r\n	INSERT INTO employees_temp VALUES(x, y);\r\n	UPDATE employees_temp SET last_name = x WHERE first_name = y;\r\n	DELETE FROM employees_temp WHERE first_name = x;\r\n	EXECUTE INMEDIATE ''INSERT INTO v_table SELECT * FROM employees_tmp'';\r\n	COMMIT;\r\nEND;\r\n/\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nEste ejemplo realiza un sustitucion de variables en diferentes sentencias DML. Podremos poner la variable directamente si la utilizamos para igualar en el SET en un UPDATE o compo predicado en el WHERE. Si queremos que la variable indique el nombre de la tabla utilizaremos la expresion EXECUTE IMMEDIATE.\r\n</div>\r\n'),
(58, '<div class="parrafo" align="justify">\r\nPLSQL puede utilizar cursores de forma implicita o de forma explicita. PLSQL utilizara un cursor de forma implicita en cada sentencia DML que ejecutemos e incluso con queries que devuelven una unica linea. Si queremos tener algo mas de control podemos definir cursores de forma explicita, por lo que sera necesario declararlos.\r\n</div>\r\n<div class="parrafo" align="justify">\r\nEjemplo cursor implicito:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>CREATE TABLE dept_temp AS SELECT * FROM departments;\r\nDECLARE\r\n	dept_no NUMBER(4) := 270;\r\nBEGIN\r\n	DELETE FROM dept_temp WHERE department_id = dept_no;\r\n	IF SQL%FOUND THEN -- delete succeeded\r\n		INSERT INTO dept_temp VALUES (270, ''Personnel'', 200, 1700);\r\n	END IF;\r\nEND;\r\n/\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nEl cursor implicito que utiliza PLSQL es el cursor SQL este cursor tiene una serie de atributos como %FOUND %NOTFOUND que indica de forma boleana si se el cursor tiene algun objeto. \r\n</div>\r\n<div class="parrafo" align="justify">\r\nEl ejemplo anterior es util para evitar violar claves primarias.\r\n</div>\r\n<div class="parrafo" align="justify">\r\nOtro atributo util de los cursores es %ROWCOUNT, que devuelve los valores afectados en sentencias DML.\r\n</div>\r\n<div class="parrafo" align="justify">\r\nEjemplo cursor implicito en un bucle FOR:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>BEGIN\r\nFOR item IN\r\n( SELECT last_name, job_id FROM employees WHERE job_id LIKE ''%CLERK%''\r\nAND manager_id &gt;12)\r\nLOOP\r\n	DBMS_OUTPUT.PUT_LINE(''Name = '' || item.last_name || '', Job = '' ||\r\n	item.job_id);\r\nEND LOOP;\r\nEND;\r\n/\r\n\r\n</p></pre></blockquote>\r\n<h3>Cursores explicitos</h3>\r\n\r\n<div class="parrafo" align="justify">\r\nAntes de utilizar un cursor de forma explicita lo tenemos que declarar:\r\n</div>\r\n<div class="parrafo" align="justify">\r\nEjemplo:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>DECLARE\r\n	  -- Declaracion 1:\r\n	CURSOR c1 IS \r\n	SELECT employee_id, job_id, salary FROM employees WHERE salary &gt; 2000;\r\n	  -- Declaracion 2:\r\n	CURSOR c2 RETURN departments%ROWTYPE IS\r\n		SELECT * FROM departments WHERE department_id = 110;\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\n\r\nA la hora de declarar un cursor tenemos que especificar la query que se tieen que ejecutar cuando abramos el cursor.\r\n</div>\r\n<div class="parrafo" align="justify">\r\nPodemos declarar un cursor para que reciba parametros que luego pueden aparecen en la query.\r\n</div>\r\n<div class="parrafo" align="justify">\r\nEjemplo:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>DECLARE\r\n	CURSOR c1 (low NUMBER DEFAULT 0, high NUMBER DEFAULT 99) IS\r\n		SELECT * \r\n		FROM departments \r\n		WHERE \r\n			department_id &gt; low AND department_id &lt; high;\r\n			\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nPara empezar a trabajar con un cursor primero debemos abrirlo:\r\n</div>\r\n<div class="parrafo" align="justify">\r\nEjemplo:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>DECLARE\r\n	CURSOR c1 IS \r\n		SELECT employee_id, last_name, job_id, salary \r\n		FROM employees\r\n		WHERE salary &gt; 2000;\r\nBEGIN\r\n	OPEN C1;\r\n	\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nY para que devuelva una linea utilizamos el comando FETCH.\r\n</div>\r\n<div class="parrafo" align="justify">\r\nEjemplo:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>DECLARE\r\n	v_jobid employees.job_id%TYPE; -- variable for job_id\r\n	v_lastname employees.last_name%TYPE; -- variable for last_name\r\n	CURSOR c1 IS \r\n	SELECT last_name, job_id FROM employees\r\n	WHERE REGEXP_LIKE (job_id, ''S[HT]_CLERK'');\r\n	v_employees employees%ROWTYPE; -- record variable for row\r\n	CURSOR c2 is \r\n	SELECT * FROM employees\r\n	WHERE REGEXP_LIKE (job_id, ''[ACADFIMKSA]_M[ANGR]'');\r\nBEGIN\r\n	OPEN c1; -- open the cursor before fetching\r\n	LOOP\r\n		FETCH c1 INTO v_lastname, v_jobid; -- fetches 2 columns into variables\r\n		EXIT WHEN c1%NOTFOUND;\r\n		DBMS_OUTPUT.PUT_LINE( RPAD(v_lastname, 25, '' '') || v_jobid );\r\n	END LOOP;\r\n	CLOSE c1;\r\n	DBMS_OUTPUT.PUT_LINE( ''-------------------------------------'' );\r\n	OPEN c2;\r\n	LOOP\r\n		FETCH c2 INTO v_employees; -- fetches entire row into the v_employees record\r\n		EXIT WHEN c2%NOTFOUND;\r\n		DBMS_OUTPUT.PUT_LINE( RPAD(v_employees.last_name, 25, '' '') || v_employees.job_id );\r\n	END LOOP;\r\n	CLOSE c2;\r\nEND;\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nCada vez que utilicemos FETCH el cursor devolvera un fila:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>DECLARE\r\n	CURSOR c1 IS \r\n		SELECT last_name FROM employees ORDER BY last_name;\r\n	name1 employees.last_name%TYPE;\r\n	name2 employees.last_name%TYPE;\r\n	name3 employees.last_name%TYPE;\r\nBEGIN\r\n	OPEN c1;\r\n	FETCH c1 INTO name1; -- this fetches first row\r\n	FETCH c1 INTO name2; -- this fetches second row\r\n	FETCH c1 INTO name3; -- this fetches third row\r\n	CLOSE c1;\r\nEND;\r\n/\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nPodemos directamente leer todos los elementos de un cursor si en el FETCH utilizamos BULK COLLECT.\r\n</div>\r\n<div class="parrafo" align="justify">\r\nEjemplo:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>DECLARE\r\n	TYPE IdsTab IS TABLE OF employees.employee_id%TYPE;\r\n	TYPE NameTab IS TABLE OF employees.last_name%TYPE;\r\n	ids IdsTab;\r\n	names NameTab;\r\n	CURSOR c1 IS\r\n	SELECT employee_id, last_name FROM employees WHERE job_id = ''ST_CLERK'';\r\nBEGIN\r\n	OPEN c1;\r\n	FETCH c1 BULK COLLECT INTO ids, names;\r\n	CLOsE c1;\r\n	-- Here is where you process the elements in the collections\r\n	FOR i IN ids.FIRST .. ids.LAST\r\n	LOOP\r\n		IF ids(i) &gt; 140 THEN\r\n			DBMS_OUTPUT.PUT_LINE( ids(i) );\r\n		END IF;\r\n	END LOOP;\r\n	FOR i IN names.FIRST .. names.LAST\r\n	LOOP\r\n		IF names(i) LIKE ''%Ma%'' THEN\r\n			DBMS_OUTPUT.PUT_LINE( names(i) );\r\n		END IF;\r\n	END LOOP;\r\nEND;\r\n/\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nComo hemos visto en los ejemplos anteriores, cuando ya hayamos terminado de operar con el cursor debemos de cerrarlo con CLOSE.\r\n</div>\r\n<div class="parrafo" align="justify">\r\nAlgunos atributos que tienen los cursores explicitos son: %FOUND, %NOTFOUND, %ISOPEN, %ROWCOUNT. %FOUND devolvera TRUE la primera vez que hagamos un FETCH del cursor. %ROWCOUNT se ira incrementando con cada FETCH  ejecutado.\r\n<div class="parrafo" align="justify">\r\n<div class="parrafo" align="justify">\r\nPodemos meter un cursor explicito dentro de un bucle FOR y no sera necesario ni abrirlo ni cerrarlo\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>DECLARE\r\n	CURSOR c1 IS \r\n		SELECT last_name, job_id FROM employees\r\n		WHERE job_id LIKE ''%CLERK%'' AND manager_id &gt; 120;\r\nBEGIN\r\n	FOR item IN c1\r\n	LOOP\r\n		DBMS_OUTPUT.PUT_LINE(''Name = '' || item.last_name || '', Job = '' ||\r\n		item.job_id);\r\n	END LOOP;\r\nEND;\r\n/\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nPodemos definir cursores que admitan parametros:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>DECLARE\r\n	CURSOR c1 (job VARCHAR2, max_wage NUMBER) IS\r\n		SELECT * FROM employees WHERE job_id = job AND salary &gt; max_wage;\r\nBEGIN\r\n	FOR person IN c1(''CLERK'', 3000)\r\n	LOOP	\r\n		-- process data record\r\n		DBMS_OUTPUT.PUT_LINE(''Name = '' || person.last_name || '', salary = '' ||\r\n		person.salary || '', Job Id = '' || person.job_id );\r\n	END LOOP;\r\nEND;\r\n/\r\n</p></pre></blockquote>'),
(59, '<div class="parrafo" align="justify">\r\nUn cursor variable es mas flexible que un cursor normal ya que no esta atado a una unica query. Lo podemos entender como un puntero a un conjunto de resultados. Para definir un cursor variable tenemos que declararlo como REF CURSOR.\r\n\r\n</div>\r\n<div class="parrafo" align="justify">\r\nUn cursor normal apunta siempre a una unica area de trabajo, mientras que un cursor variable puede apuntar a varias areas de trabajo.\r\n</div>\r\n<div class="parrafo" align="justify">\r\nLos cursores variables se declaran:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>DECLARE\r\n	TYPE DeptCurTyp IS REF CURSOR RETURN departments%ROWTYPE; -- fuerte.\r\n	TYPE genericcurtyp IS REF CURSOR; -- debil\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nUnicamente indica el tipo de registro que va a devolver tambien podemos no indicar el tipo, pero esta forma oracle la considera debil ya que puede originar errores.\r\n</div>\r\n<div class="parrafo" align="justify">\r\nPara utilizar el cursor necesitamos una variable:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>DECLARE\r\n	TYPE DeptCurTyp IS REF CURSOR RETURN departments%ROWTYPE; -- fuerte.\r\n	tmp_cv DeptCurTyp;\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nTambien podemos crear un cursor que apunte a un record:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>DECLARE\r\n	TYPE EmpRecTyp IS RECORD (\r\n		employee_id NUMBER,\r\n		last_name VARCHAR2(25),\r\n		salary NUMBER(8,2));\r\n	TYPE EmpCurTyp IS REF CURSOR RETURN EmpRecTyp;\r\n	emp_cv EmpCurTyp; -- declare cursor variable\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nEjemplo de utilizacion de un cursor variable:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>DECLARE\r\n	TYPE empcurtyp IS REF CURSOR RETURN employees%ROWTYPE;\r\n	emp empcurtyp;\r\n	PROCEDURE process_emp_cv (emp_cv IN empcurtyp) IS\r\n	person employees%ROWTYPE;\r\n	BEGIN\r\n		DBMS_OUTPUT.PUT_LINE(''Here are the names from the result set:'');\r\n		LOOP\r\n		FETCH emp_cv INTO person;\r\n			EXIT WHEN emp_cv%NOTFOUND;\r\n			DBMS_OUTPUT.PUT_LINE(''Name = '' || person.first_name ||'' '' || person.last_name);\r\n		END LOOP;\r\n	END;\r\nBEGIN\r\n	-- First find 10 arbitrary employees.\r\n	OPEN emp FOR SELECT * FROM employees WHERE ROWNUM &lt; 11;\r\n	process_emp_cv(emp);\r\n	CLOSE emp;\r\n	-- find employees matching a condition.\r\n	OPEN emp FOR SELECT * FROM employees WHERE last_name LIKE ''R%'';\r\n	process_emp_cv(emp);\r\n	CLOSE emp;\r\nEND;\r\n/\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nComo podemos ver los valores que recibe este cursor salen de esta sentencia:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>OPEN emp FOR SELECT * FROM employees WHERE last_name LIKE ''R%'';\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nEn el ejemplo se ven como los comandos que rigen el cursor son OPEN - FOR, FETCH y CLOSE.\r\n</div>\r\n<div class="parrafo" align="justify">\r\nEjemplo:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>BEGIN\r\n	IF choice = 1 THEN\r\n		OPEN emp_cv FOR SELECT * FROM employees WHERE commission_pct IS NOT NULL;\r\n	ELSIF choice = 2 THEN\r\n		OPEN emp_cv FOR SELECT * FROM employees WHERE salary &gt; 2500;\r\n	ELSIF choice = 3 THEN\r\n		OPEN emp_cv FOR SELECT * FROM employees WHERE department_id = 100;\r\n	END IF;\r\nEND;\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nEjemplo simple de como utilizar un cursor variable:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>DECLARE\r\nTYPE empcurtyp IS REF CURSOR RETURN employees%ROWTYPE;\r\n	emp_cv empcurtyp;\r\n	emp_rec employees%ROWTYPE;\r\nBEGIN\r\n	OPEN emp_cv FOR SELECT * FROM employees WHERE employee_id &lt; <div class="parrafo" align="justify">0;\r\n	LOOP\r\n	FETCH emp_cv INTO emp_rec; -- fetch from cursor variable\r\n	EXIT WHEN emp_cv%NOTFOUND; -- exit when last row is fetched\r\n		-- process data record\r\n		DBMS_OUTPUT.PUT_LINE(''Name = '' || emp_rec.first_name || '' '' ||emp_rec.last_name);\r\n	END LOOP;\r\nCLOSE emp_cv;\r\nEND;\r\n/\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nEjemplo, utilizando BULK COLLECT para meter en una coleccion varias lineas.\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>DECLARE\r\n	TYPE empcurtyp IS REF CURSOR;\r\n	TYPE namelist IS TABLE OF employees.last_name%TYPE;\r\n	TYPE sallist IS TABLE OF employees.salary%TYPE;\r\n	emp_cv empcurtyp;\r\n	names namelist;\r\n	sals sallist;\r\nBEGIN\r\n	OPEN emp_cv FOR SELECT last_name, salary FROM employees\r\n	WHERE job_id = ''SA_REP'';\r\n		FETCH emp_cv BULK COLLECT INTO names, sals;\r\n		CLOSE emp_cv;\r\n		-- loop through the names and sals collections\r\n		FOR i IN names.FIRST .. names.LAST\r\n		LOOP\r\n			DBMS_OUTPUT.PUT_LINE(''Name = '' || names(i) || '', salary = '' || sals(i));\r\n		END LOOP;\r\nEND;\r\n/\r\n</p></pre></blockquote>\r\n'),
(60, '<div class="parrafo" align="justify">\r\nNos puede interesar realizar un conteo o un estudio de los registros de una tabla que cumplen una determinada query y estar seguro que mientras estamos realizando ese estudio ningun otro usuario nos modifica esos registros. En este caso podemos utilizar SELECT FOR UPDATE que realizan un bloqueo de esas filas hasta que ejecutemos un commit o un rollback de nuestra transaccion.\r\n</div>\r\n<div class="parrafo" align="justify">\r\nEjemplo:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>DECLARE\r\n	CURSOR c1 IS \r\n		SELECT employee_id, salary FROM employees\r\n		WHERE job_id = ''SA_REP'' AND commission_pct &gt; .10\r\n	FOR UPDATE NOWAIT;\r\n	\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nPodemos utilizar NOWAIT para que en el caso que una de las filas afectadas por nuestra query se encuentra  bloqueada por otro usuario.\r\n</div>\r\n<div class="parrafo" align="justify">\r\nSi utilizamos SELECT FOR UPDATE sobre una query con multiples tablas se produce un bloqueo sobre esas tablas, pero si unicamente tenemos pensado modificar el  los registros de una unica tabla podemos hacer SELECT FOR UPDATE OF &lt;Tabla&gt;.\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>DECLARE\r\n	CURSOR c1 IS \r\n		SELECT last_name, department_name FROM employees, departments\r\n		WHERE employees.department_id = departments.department_id\r\n		AND job_id = ''SA_MAN''\r\n		FOR UPDATE OF salary;\r\n</p></pre></blockquote>\r\n'),
(61, '<div class="parrafo" align="justify">\r\nEn este post vamos a introducir la definicion de SQL dinamico. Esto consiste en construir sentencias de SQL en tiempo de ejecucion. Para ello utilizaremos la sencentia EXECUTE IMMEDIATE. Junto con este comando podemos utilizar las sentencias INTO, USING y RETURNING INTO.\r\n</div>\r\n<h3>Ejemplo 1:</h3>\r\n\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>CREATE OR REPLACE PROCEDURE raise_emp_salary (column_value NUMBER,\r\n	emp_column VARCHAR2, amount NUMBER) IS\r\n	v_column VARCHAR2(30);\r\n	sql_stmt VARCHAR2(200);\r\nBEGIN\r\n	-- determine if a valid column name has been given as input\r\n	SELECT COLUMN_NAME INTO v_column FROM USER_TAB_COLS	\r\n		WHERE TABLE_NAME = ''EMPLOYEES'' AND COLUMN_NAME = emp_column;\r\n	sql_stmt := ''UPDATE employees SET salary = salary + :1 WHERE ''|| v_column || '' = :2'';\r\n	EXECUTE IMMEDIATE sql_stmt USING amount, column_value;\r\n	IF SQL%ROWCOUNT &gt; 0 THEN\r\n		DBMS_OUTPUT.PUT_LINE(''Salaries have been updated for: '' || emp_column|| '' = '' || column_value);\r\n	END IF;\r\nEXCEPTION\r\nWHEN NO_DATA_FOUND THEN\r\n	DBMS_OUTPUT.PUT_LINE (''Invalid Column: '' || emp_column);\r\nEND raise_emp_salary;\r\n/\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nEn la sentencia EXECUTE IMMEDIATE vemos como puede utilizar variables con el formato :mi_variable, para asignarle valor a esas variables utiliza USING.\r\n</div>\r\n<h3>Ejemplo 2:</h3>\r\n\r\n\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>CREATE TABLE employees_temp AS SELECT * FROM employees;\r\n\r\nCREATE OR REPLACE PROCEDURE delete_rows (\r\n	table_name IN VARCHAR2,\r\n	condition IN VARCHAR2 DEFAULT NULL) AS\r\n	where_clause VARCHAR2(100) := '' WHERE '' || condition;\r\n	v_table VARCHAR2(30);\r\nBEGIN\r\n	-- first make sure that the table actually exists; if not, raise an exception\r\n	SELECT OBJECT_NAME INTO v_table FROM USER_OBJECTS\r\n	WHERE OBJECT_NAME = UPPER(table_name) AND OBJECT_TYPE = ''TABLE'';\r\n	IF condition IS NULL THEN \r\n		where_clause := NULL; \r\n	END IF;\r\n	EXECUTE IMMEDIATE ''DELETE FROM '' || v_table || where_clause;\r\nEXCEPTION\r\n	WHEN NO_DATA_FOUND THEN\r\n	DBMS_OUTPUT.PUT_LINE (''Invalid table: '' || table_name);\r\nEND;\r\n/\r\nBEGIN\r\n	delete_rows(''employees_temp'', ''employee_id = 111'');\r\nEND;\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nEn este ejemplo vemos como con EXECUTE IMMEDIATE podemos ademas de definir las variables que configuran el predicado configurar nombres de tabla y columnas.\r\n</div>\r\n\r\n<h3>Ejemplo 3:</h3>\r\n\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>CREATE PROCEDURE create_dept (\r\n	deptid IN OUT NUMBER,\r\n	dname IN VARCHAR2,\r\n	mgrid IN NUMBER,\r\n	locid IN NUMBER) AS\r\nBEGIN\r\n	SELECT departments_seq.NEXTVAL INTO deptid FROM dual;\r\n	INSERT INTO departments VALUES (deptid, dname, mgrid, locid);\r\nEND;\r\n/\r\n\r\nDECLARE\r\n	plsql_block VARCHAR2(500);\r\n	new_deptid NUMBER(4);\r\n	new_dname VARCHAR2(30) := ''Advertising'';\r\n	new_mgrid NUMBER(6) := 200;\r\n	new_locid NUMBER(4) := 1700;\r\nBEGIN\r\n	plsql_block := ''BEGIN create_dept(:a, :b, :c, :d); END;'';\r\n	EXECUTE IMMEDIATE plsql_block\r\n	USING IN OUT new_deptid, new_dname, new_mgrid, new_locid;\r\nEND;\r\n/\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nvemos como parametrizamos USING con IN OUT y asi poder utilizar esas variables tanto de entrada como de salida.\r\n</div>\r\n<h3>Ejemplo 4:</h3>\r\n\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>DECLARE\r\n	TYPE EmpCurTyp IS REF CURSOR;\r\n	emp_cv EmpCurTyp;\r\n	emp_rec employees%ROWTYPE;\r\n	sql_stmt VARCHAR2(200);\r\n	v_job VARCHAR2(10) := ''ST_CLERK'';\r\nBEGIN\r\n	sql_stmt := ''SELECT * FROM employees WHERE job_id = :j'';\r\n	OPEN emp_cv FOR sql_stmt USING v_job;\r\n	LOOP\r\n		FETCH emp_cv INTO emp_rec;\r\n		EXIT WHEN emp_cv%NOTFOUND;\r\n		DBMS_OUTPUT.PUT_LINE(''Name: '' || emp_rec.last_name || '' Job Id: '' ||emp_rec.job_id);\r\n	END LOOP;\r\n	CLOSE emp_cv;\r\nEND;\r\n/\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nVemos como podemos utilizar SQL diniamico con cursores variables.\r\n</div>');
INSERT INTO `ENTRADA_TEXTO` (`ID_ENTRADA`, `TEXTO`) VALUES
(62, '<div class="parrafo" align="justify">\r\nExisten dos tipos de subprogramas en PLSQL: Funciones y Procedimientos.\r\n</div>\r\n<h3>Ejemplo procedimiento:</h3>\r\n\r\n\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>DECLARE\r\n	in_string VARCHAR2(100) := ''''This is my test string.'''';\r\n	out_string VARCHAR2(200);\r\n	PROCEDURE double ( original IN VARCHAR2, new_string OUT VARCHAR2 ) AS\r\n	BEGIN\r\n		new_string := original || '''' + '''' || original;\r\n	EXCEPTION\r\n		WHEN VALUE_ERROR THEN\r\n		DBMS_OUTPUT.PUT_LINE(''''Output buffer not long enough.'''');\r\n	END;\r\nBEGIN\r\n	double(in_string, out_string);\r\n	DBMS_OUTPUT.PUT_LINE(in_string || '''' - '''' || out_string);\r\nEND;\r\n/\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nVemos como se pude declarar un procedimiento dentro de un bloque de PLSQL\r\n</div>\r\n<h3>Ejemplo funcion:</h3>\r\n\r\n\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>DECLARE\r\n	FUNCTION square(original NUMBER)\r\n	RETURN NUMBER AS original_squared NUMBER;\r\n	BEGIN\r\n		original_squared := original * original;\r\n		RETURN original_squared;\r\n	END;\r\nBEGIN\r\n	DBMS_OUTPUT.PUT_LINE(square(100));\r\nEND;\r\n/\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nTanto la funcion como el procedimiento de los ejemplos anteriores son subprogramas temporales, que permaneceran mientras dura la ejecucion del bolque. Para poder crearlos como objetos de Oracle, tendremos que utilizar CREATE PROCEDURE o CREATE FUNCTION.\r\n</div>\r\n<div class="parrafo" align="justify">\r\nComo vemos la diferencia entre el procedimiento y la funcion es qeu el procedimiento no devuelve ningun valor mientras que en la definicion de la funcion tenemos que indicar el valor qeu vamos a devolver.\r\n</div>\r\n<h3>Ejemplo crear funcion:</h3>\r\n\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>CREATE OR REPLACE FUNCTION half_of_square(original NUMBER)\r\nRETURN NUMBER IS\r\nBEGIN\r\n	RETURN (original * original)/2 + (original * 4);\r\nEND half_of_square;\r\n/\r\n\r\n</p></pre></blockquote>\r\n<h3>Ejemplo procedimientos anidados:</h3>\r\n\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>DECLARE\r\n	PROCEDURE proc1(number1 NUMBER); -- forward declaration\r\n	PROCEDURE proc2(number2 NUMBER) IS\r\n	BEGIN\r\n		proc1(number2); -- calls proc1\r\n	END;\r\n	\r\n	PROCEDURE proc1(number1 NUMBER) IS\r\n	BEGIN\r\n		proc2 (number1); -- calls proc2\r\n	END;\r\nBEGIN\r\n	NULL;\r\nEND;\r\n/\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nEn un bloque PLSQL puede haber funciones que se invoquen entre si. Para poder utilizarlas una de ellas la tenemos que declarar primero.\r\n</div>\r\n<h3>Ejemplo paso de parametros:</h3>\r\n\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>DECLARE\r\n	emp_num NUMBER(6) := 120;\r\n	bonus NUMBER(6) := 100;\r\n	merit NUMBER(4) := 50;\r\n	PROCEDURE raise_salary (emp_id NUMBER, amount NUMBER) IS\r\n	BEGIN\r\n		UPDATE employees SET salary = salary + amount WHERE employee_id = emp_id;\r\n	END raise_salary;\r\nBEGIN\r\n	raise_salary(emp_num, bonus); -- procedure call specifies actual parameters\r\n	raise_salary(emp_num, merit + bonus); -- expressions can be used as parameters\r\nEND;\r\n/\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nVemos como una funcion puede utilizar varios tipos de parametros, lo que se meten en la llamada de la funcion y los que se declaran antes que el procedimiento.\r\n</div>\r\n<h3>Ejemplo utilizar parametros de salida:</h3>\r\n\r\n\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>DECLARE\r\n	emp_num NUMBER(6) := <div class="parrafo" align="justify">0;\r\n	bonus NUMBER(6) := 50;\r\n	emp_last_name VARCHAR2(25);\r\n	PROCEDURE raise_salary (emp_id IN NUMBER, amount IN NUMBER,emp_name OUT VARCHAR2) IS\r\n	BEGIN\r\n		UPDATE employees SET salary = salary + amount WHERE employee_id = emp_id;\r\n		SELECT last_name INTO emp_name FROM employees WHERE employee_id = emp_id;\r\n	END raise_salary;\r\nBEGIN\r\n	raise_salary(emp_num, bonus, emp_last_name);\r\n	DBMS_OUTPUT.PUT_LINE(''''Salary has been updated for: '''' || emp_last_name);\r\nEND;\r\n/\r\n\r\n</p></pre></blockquote>\r\n<h3>Ejemplo, utilizar valores por defecto:</h3>\r\n\r\n\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>DECLARE\r\n	emp_num NUMBER(6) := 120;\r\n	bonus NUMBER(6);\r\n	merit NUMBER(4);\r\n	PROCEDURE raise_salary (emp_id IN NUMBER, amount IN NUMBER DEFAULT 100,\r\n	extra IN NUMBER DEFAULT 50) IS\r\n	BEGIN\r\n		UPDATE employees SET salary = salary + amount + extra WHERE employee_id = emp_id;\r\n	END raise_salary;\r\nBEGIN\r\n	raise_salary(120); -- same as raise_salary(120, 100, 50)\r\n	raise_salary(emp_num, extra =&gt; 25); -- same as raise_salary(120, 100, 25)\r\nEND;\r\n/\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nVemos que se puede asociar el nombre del parametro con el valor utilizando =&gt;\r\n</div>\r\n\r\n'),
(63, '<div class="parrafo" align="justify">\r\nUn paquete es un objeto de base de datos que lo podemos entender como un conjunto de subprogramas, variables y tipos de PL/SQL. Un paquete esta compuesto por una cabecera y un cuerpo. La cabecera del paquete es donde especificamos los subprogramas que componen el paquete o las variables globales que van poder utilizar esos subprogramas. Los subprogramas declarados en la cabecera del paquete son los que van a poder ser invocados por los usuarios.\r\n</div>\r\n<h3>Ejemplo de cabecera:</h3>\r\n\r\n\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>\r\nCREATE PACKAGE trans_data AS -- bodiless package\r\n	TYPE TimeRec IS RECORD (\r\n		minutes SMALLINT,\r\n		hours SMALLINT);\r\n\r\n	TYPE TransRec IS RECORD (\r\n		category VARCHAR2(10),\r\n		account INT,\r\n		amount REAL,\r\n		time_of TimeRec);\r\n\r\n	minimum_balance CONSTANT REAL := 10.00;\r\n	number_processed INT;\r\n	insufficient_funds EXCEPTION;\r\n	\r\nEND trans_data;\r\n/\r\n\r\n</p></pre></blockquote>\r\n<h3>Ejemplo de cuerpo de un paquete:</h3>\r\n\r\n\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>\r\nCREATE PACKAGE emp_bonus AS\r\n	PROCEDURE calc_bonus (date_hired employees.hire_date%TYPE);\r\n	END emp_bonus;\r\n/\r\n\r\nCREATE PACKAGE BODY emp_bonus AS\r\n	PROCEDURE calc_bonus (date_hired employees.hire_date%TYPE) IS\r\n	BEGIN\r\n		DBMS_OUTPUT.PUT_LINE(''Employees hired on '' || date_hired || '' get bonus.'');\r\n	END;\r\nEND emp_bonus;\r\n/\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\n\r\nEl cuerpo del paquete puede tener declaraciones privadas, que seran funciones a las que podran llamar el resto de subprogramas, pero que no podran ser accesibles por los usuarios.\r\n</div>\r\n<h3>Ejemplo de definicion y utilizacion de un paquete:</h3>\r\n\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>\r\nCREATE TABLE emp_audit(date_of_action DATE, user_id VARCHAR2(20),package_name VARCHAR2(30));\r\n\r\nCREATE OR REPLACE PACKAGE emp_admin AS\r\n	TYPE EmpRecTyp IS RECORD (emp_id NUMBER, sal NUMBER);\r\n\r\n	CURSOR desc_salary RETURN EmpRecTyp;\r\n	\r\n	invalid_salary EXCEPTION;\r\n	\r\n	FUNCTION hire_employee (last_name VARCHAR2, first_name VARCHAR2,\r\n	email VARCHAR2, phone_number VARCHAR2, job_id VARCHAR2, salary NUMBER,\r\n	commission_pct NUMBER, manager_id NUMBER, department_id NUMBER)	RETURN NUMBER;\r\n	\r\n	PROCEDURE fire_employee (emp_id NUMBER); -- overloaded subprogram\r\n	\r\n	PROCEDURE fire_employee (emp_email VARCHAR2); -- overloaded subprogram\r\n	\r\n	PROCEDURE raise_salary (emp_id NUMBER, amount NUMBER);\r\n	\r\n	FUNCTION nth_highest_salary (n NUMBER) RETURN EmpRecTyp;\r\nEND emp_admin;\r\n/\r\n\r\nCREATE OR REPLACE PACKAGE BODY emp_admin AS\r\n	number_hired NUMBER; -- variable privada\r\n	CURSOR desc_salary RETURN EmpRecTyp IS\r\n		SELECT employee_id, salary FROM employees ORDER BY salary DESC;\r\n	FUNCTION hire_employee (last_name VARCHAR2, first_name VARCHAR2,\r\n		email VARCHAR2, phone_number VARCHAR2, job_id VARCHAR2, salary NUMBER,\r\n		commission_pct NUMBER, manager_id NUMBER, department_id NUMBER)\r\n	RETURN NUMBER IS new_emp_id NUMBER;\r\n	BEGIN\r\n		SELECT employees_seq.NEXTVAL INTO new_emp_id FROM dual;\r\n		INSERT INTO employees VALUES (new_emp_id, last_name, first_name, email,\r\n			phone_number, SYSDATE, job_id, salary, commission_pct, manager_id,\r\n			department_id);\r\n		number_hired := number_hired + 1;\r\n		DBMS_OUTPUT.PUT_LINE(''The number of employees hired is ''|| TO_CHAR(number_hired) );\r\n		RETURN new_emp_id;\r\n	END hire_employee;\r\n	\r\n	PROCEDURE fire_employee (emp_id NUMBER) IS\r\n	BEGIN\r\n		DELETE FROM employees WHERE employee_id = emp_id;\r\n	END fire_employee;\r\n	\r\n	PROCEDURE fire_employee (emp_email VARCHAR2) IS\r\n	BEGIN\r\n		DELETE FROM employees WHERE email = emp_email;\r\n	END fire_employee;\r\n\r\n	-- Funcion privada\r\n	FUNCTION sal_ok (jobid VARCHAR2, sal NUMBER) RETURN BOOLEAN IS\r\n		min_sal NUMBER;\r\n		max_sal NUMBER;\r\n	BEGIN\r\n		SELECT MIN(salary), MAX(salary) INTO min_sal, max_sal FROM employees\r\n		WHERE job_id = jobid;\r\n		RETURN (sal &gt;= min_sal) AND (sal &lt;= max_sal);\r\n	END sal_ok;\r\n\r\n	PROCEDURE raise_salary (emp_id NUMBER, amount NUMBER) IS\r\n		sal NUMBER(8,2);\r\n		jobid VARCHAR2(10);\r\n	BEGIN\r\n		SELECT job_id, salary INTO jobid, sal FROM employees\r\n		WHERE employee_id = emp_id;\r\n		IF sal_ok(jobid, sal + amount) THEN\r\n			UPDATE employees SET salary = salary + amount WHERE employee_id = emp_id;\r\n		ELSE\r\n			RAISE invalid_salary;\r\n		END IF;\r\n	EXCEPTION\r\n		WHEN invalid_salary THEN\r\n		DBMS_OUTPUT.PUT_LINE(''The salary is out of the specified range.'');\r\n	END raise_salary;\r\n\r\n	FUNCTION nth_highest_salary (n NUMBER) RETURN EmpRecTyp IS\r\n		emp_rec EmpRecTyp;\r\n	BEGIN\r\n		OPEN desc_salary;\r\n		FOR i IN 1..n LOOP\r\n			FETCH desc_salary INTO emp_rec;\r\n		END LOOP;\r\n		CLOSE desc_salary;\r\n		RETURN emp_rec;\r\n	END nth_highest_salary;\r\n	\r\nBEGIN -- parte para la inicializacion\r\n	INSERT INTO emp_audit VALUES (SYSDATE, USER, ''EMP_ADMIN'');\r\n	number_hired := 0;\r\nEND emp_admin;\r\n/\r\n\r\n-- LLamada de la funcion.\r\nDECLARE\r\n	new_emp_id NUMBER(6);\r\nBEGIN\r\n	new_emp_id := emp_admin.hire_employee(''Belden'', ''Enrique'', ''EBELDEN'',\r\n	''555.111.2222'', ''ST_CLERK'', 2500, .1, 101, 110);\r\n	DBMS_OUTPUT.PUT_LINE(''The new employee id is '' || TO_CHAR(new_emp_id) );\r\n	EMP_ADMIN.raise_salary(new_emp_id, 100);\r\n	DBMS_OUTPUT.PUT_LINE(''The 10th highest salary is ''||\r\n	TO_CHAR(emp_admin.nth_highest_salary(10).sal) || '', belonging to employee: ''\r\n	|| TO_CHAR(emp_admin.nth_highest_salary(10).emp_id) );\r\n	emp_admin.fire_employee(new_emp_id);\r\nEND;\r\n/\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nComo vemos para poder utilizar un paquete utilizamos el nombre del paquete.procedimiento.\r\n</div>\r\n'),
(64, '<div class="parrafo" align="justify">\r\nEn este post vamos a ver como se controlan los errores que se pueden originar en nuestros programas.\r\n</div>\r\n<div class="parrafo" align="justify">\r\nLas excepciones o errores que se producen en nuestros bloques PLSQL se procesan en la zona de EXCEPTION.\r\n</div>\r\n<div class="parrafo" align="justify">\r\nEjemplo:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>DECLARE\r\n	stock_price NUMBER := 9.73;\r\n	net_earnings NUMBER := 0;\r\n	pe_ratio NUMBER;\r\nBEGIN\r\n	-- Generamos una excepcion\r\n	pe_ratio := stock_price / net_earnings; \r\n	DBMS_OUTPUT.PUT_LINE(''Price/earnings ratio = '' || pe_ratio);\r\nEXCEPTION -- exception handlers begin\r\n	WHEN ZERO_DIVIDE THEN -- handles ''division by zero'' error\r\n		DBMS_OUTPUT.PUT_LINE(''Company must have had zero earnings.'');\r\n		pe_ratio := NULL;\r\nWHEN OTHERS THEN -- handles all other errors\r\n	DBMS_OUTPUT.PUT_LINE(''Some other kind of error occurred.'');\r\npe_ratio := NULL;\r\nEND; \r\n/\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nComo se puede ver en el ejemplo la zona de exception utilizamos subbloques WHEN para recoger las excepciones que se produzcan de forma independiente. La estructura dentro del EXCEPTION seria:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>EXCEPTION\r\n	WHEN exception1 THEN -- handler for exception1\r\n		sequence_of_statements1\r\n	WHEN exception2 THEN -- another handler for exception2\r\n		sequence_of_statements2\r\n	WHEN OTHERS THEN -- optional handler for all other errors\r\n		sequence_of_statements3\r\nEND;\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nLa excepcion de tipo OTHERS es la generica donde caerian las excepciones no controladas de bloques anteriores.\r\n</div>\r\n<div class="parrafo" align="justify">\r\nPLSQL permite la posibilidad de definir nuestros propias excepciones.\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>DECLARE\r\n	past_due EXCEPTION;\r\n	acct_num NUMBER;\r\nBEGIN\r\n	DECLARE\r\n		past_due EXCEPTION;\r\n		acct_num NUMBER;\r\n		due_date DATE := SYSDATE - 1;\r\n		todays_date DATE := SYSDATE;\r\n	BEGIN\r\n		IF due_date &lt; todays_date THEN\r\n			RAISE past_due; -- this is not handled\r\n		END IF;\r\n	END;\r\nEXCEPTION\r\n	WHEN past_due THEN\r\n		DBMS_OUTPUT.PUT_LINE(''Handling PAST_DUE exception.'');\r\n	WHEN OTHERS THEN\r\n		DBMS_OUTPUT.PUT_LINE(''Could not recognize PAST_DUE_EXCEPTION in this scope.'');\r\nEND;\r\n/\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nPara provocar una excepcion creada por el usuario tenemos que utilizar el comando RISE &lt;MiExcepcion&gt;\r\n</div>\r\n<div class="parrafo" align="justify">\r\nTambien podemos hacer nuestros propios codigos de error, con sus mensajes asociados:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>DECLARE\r\n	num_tables NUMBER;\r\nBEGIN\r\n	SELECT COUNT(*) INTO num_tables FROM USER_TABLES;\r\n	IF num_tables &lt; 1000 THEN\r\n		raise_application_error(-20101, ''Expecting at least 1000 tables'');\r\n	ELSE\r\n		NULL;\r\n	END IF;\r\nEND;\r\n/\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nHay que tener en cuenta que si una excepcion no se controla en su bloque EXCEPTION, debera de ser controlada en bloques EXCEPTION superiores. Si definiesemos una excepcion y no la controlasemos Oracle devolveria este error:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>ORA-06510: PL/SQL: unhandled user-defined exception\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nPodemos propagar excepciones a niveles superiores haciendo un RISE al nivel superior:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>DECLARE\r\n	salary_too_high EXCEPTION;\r\n	current_salary NUMBER := 20000;\r\n	max_salary NUMBER := 10000;\r\n	erroneous_salary NUMBER;\r\nBEGIN\r\n	BEGIN\r\n		IF current_salary &gt; max_salary THEN\r\n			RAISE salary_too_high; -- raise the exception\r\n		END IF;\r\n	EXCEPTION\r\n		WHEN salary_too_high THEN\r\n			DBMS_OUTPUT.PUT_LINE(''Salary '' || erroneous_salary || '' is out of range.'');\r\n			DBMS_OUTPUT.PUT_LINE(''Maximum salary is '' || max_salary || ''.'');\r\n			RAISE; -- relanza la misma excepcion\r\n	END;\r\nEXCEPTION\r\n	WHEN salary_too_high THEN\r\n		erroneous_salary := current_salary;\r\n		current_salary := max_salary;\r\n		DBMS_OUTPUT.PUT_LINE(''Revising salary from '' || erroneous_salary ||\r\n							 '' to '' || current_salary || ''.'');\r\nEND;\r\n/\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nDentro del bloque exception podemos obtener informacion de la excepcion producida utilizando las variables SQLCODE y SQLERRM.\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>DECLARE\r\n	name employees.last_name%TYPE;\r\n	v_code NUMBER;\r\n	v_errm VARCHAR2(64);\r\nBEGIN\r\n	SELECT last_name INTO name FROM employees WHERE employee_id = -1;\r\nEXCEPTION\r\n	WHEN OTHERS THEN\r\n		v_code := SQLCODE;\r\n		v_errm := SUBSTR(SQLERRM, 1 , 64);\r\n		DBMS_OUTPUT.PUT_LINE(''Error code '' || v_code || '': '' || v_errm);\r\n		INSERT INTO errors VALUES (v_code, v_errm, SYSTIMESTAMP);\r\nEND;\r\n/\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nEjemplo practico para comprobar en que parte del codigo se ha producido una excepcion:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>CREATE OR REPLACE PROCEDURE loc_var AS\r\n	stmt_no NUMBER;\r\n	name VARCHAR2(100);\r\nBEGIN\r\n	stmt_no := 1;\r\n	SELECT table_name INTO name FROM user_tables WHERE table_name LIKE ''ABC%'';\r\n	stmt_no := 2;\r\n	SELECT table_name INTO name FROM user_tables WHERE table_name LIKE ''XYZ%'';\r\nEXCEPTION\r\n	WHEN NO_DATA_FOUND THEN\r\n		DBMS_OUTPUT.PUT_LINE(''Table name not found in query '' || stmt_no);\r\nEND;\r\n/\r\nCALL loc_var();\r\n\r\n</p></pre></blockquote>\r\n'),
(65, '<div class="parrafo" align="justify">\r\n\r\nDataPump Export se utiliza mediante el comando expdp. Los datos exportados se almacenan en ficheros en un formato binario. Antes de realizar un export es necesario crear un directorio.\r\n</div>\r\n<div class="parrafo" align="justify">\r\nModos de export:\r\n</div>\r\n<h3>a) Full Export Mode</h3>\r\n\r\n<div class="parrafo" align="justify">\r\nRealiza el export de toda la base de datos. Es necesario tener el role de EXP_FULL_DATABASE. El parametro a utilizar seria FULL={y|n}. No se exportaran los objetos propios del sistema.\r\n</div>\r\n<div class="parrafo" align="justify">\r\nEjemplo:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>&gt; expdp hr/hr DIRECTORY=dpump_dir2 DUMPFILE=expfull.dmp FULL=y NOLOGFILE=y\r\n\r\n</p></pre></blockquote>\r\n<h3>b) Schema Mode</h3>\r\n\r\n<div class="parrafo" align="justify">\r\nCon este modo exportamos los esquemas que especifiquemos el el comando SCHEMAS. No se exportaran objetos de referencias cruzadas entre objetos. Es necesario tener el role de EXP_FULL_DATABASE.\r\n</div>\r\n<div class="parrafo" align="justify">\r\nSintaxis:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>SCHEMAS=schema_name[, ...]\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nEjemplo:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>&gt; expdp hr/hr DIRECTORY=dpump_dir1 DUMPFILE=expdat.dmp SCHEMAS=hr,sh,oe\r\n\r\n</p></pre></blockquote>\r\n<h3>c) Table Mode</h3>\r\n\r\n<div class="parrafo" align="justify">\r\nExportamos las tablas, particiones y objetos relacionados de las tablas que especifiquemos. Si la tabla no pertenece al schema del usuario que lanza el export hay que anteponer el nombre del esquema.\r\n</div>\r\n<div class="parrafo" align="justify">\r\nSintaxis:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>TABLES=[schema_name.]table_name[:partition_name] [, ...]\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nPodemos utilizar caracteres comodin para filtrar varias tablas TABLES=emp%.\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif"><pre><p>\r\n&gt; expdp hr/hr DIRECTORY=dpump_dir1 \r\n		DUMPFILE=tables.dmp\r\n		TABLES=employees,jobs,departments\r\n\r\n</p></pre></blockquote>\r\n<h3>d) Tablespace mode</h3>\r\n\r\n<div class="parrafo" align="justify">\r\nExportara aquellas tablas que pertenecen a ese tablespace. Los objetos dependientes de esas tablas tambien seran exportados. Si cualquier parte de una tabla pertenece al tablespace especificado, toda la tabla sera exportada.\r\n</div>\r\n<div class="parrafo" align="justify">\r\nSintaxis:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>TABLESPACES=tablespace_name [, ...]\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nEjemplo:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>&gt; expdp hr/hr DIRECTORY=dpump_dir1 \r\n			DUMPFILE=tbs.dmp\r\n			TABLESPACES=tbs_4, tbs_5, tbs_6\r\n			\r\n</p></pre></blockquote>\r\n<h3>e) Transportable Tablespace Mode</h3>\r\n\r\n<div class="parrafo" align="justify">\r\nNos exporta los metadatos de las tablas y los objetos de esas tablas que contiene el tablespace especificado. Tiene algunas limitaciones como que las las tablas tienen que estar incluidas en su totalidad en los tablespaces especificados. No podemos utilizar paralelismo.\r\n</div>\r\n<div class="parrafo" align="justify">\r\nSintaxis:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>TRANSPORT_TABLESPACES=tablespace_name [, ...]\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nEjemplo:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>&gt; expdp hr/hr DIRECTORY=dpump_dir1 \r\n				DUMPFILE=tts.dmp\r\n				TRANSPORT_TABLESPACES=tbs_1 \r\n				TRANSPORT_FULL_CHECK=y LOGFILE=tts.log\r\n\r\n</p></pre></blockquote>\r\nComandos\r\n<div class="parrafo" align="justify">\r\n<strong>1. CONTENT</strong>: Si vamos a exportar todos, solo los datos o solo los metadatos. Esta limitado unicamente al modo esquema.\r\n</div>\r\n<div class="parrafo" align="justify">\r\nSintaxis:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>CONTENT={ALL | DATA_ONLY | METADATA_ONLY}\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nEjemplo:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>	&gt; expdp hr/hr DIRECTORY=dpump_dir1 DUMPFILE=hr.dmp CONTENT=METADATA_ONLY\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\n<strong>2. DIRECTORY</strong>: Indica el objeto directorio donde se van a dejar los datos. Por defecto utiliza DATA_PUMP_DIR.\r\n</div>\r\n<div class="parrafo" align="justify">\r\nSintaxis:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>DIRECTORY=directory_object\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nEjemplo:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>&gt; expdp hr/hr DIRECTORY=dpump_dir1 DUMPFILE=employees.dmp CONTENT=METADATA_ONLY\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\n<strong>3. DUMPFILE</strong>: Es el nombre de los ficheros que vamos a exportar. Por defecto sera expdat.dmp. Podemo utilizar %U para que vayan generando diferentes ficheros utilizando dos digitos para listarlos.\r\n</div>\r\n<div class="parrafo" align="justify">\r\nSintaxis:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>DUMPFILE=[directory_object:]file_name [, ...]\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nEjemplo:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>&gt; expdp hr/hr SCHEMAS=hr DIRECTORY=dpump_dir1 \r\n				DUMPFILE=dpump_dir2:exp1.dmp, exp2%U.dmp\r\n				PARALLEL=3\r\n				\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\n<strong>4. ESTIMATE</strong>: Indicamos el metodo que vamos a utilizar para estimar cuento espacion en disco va a ocupar el export. Puede ser por bloques o por estadisticas. El export de las tablas realiza un compresion de los datos, a la hora de estimar no se tiene en cuenta eso.\r\n</div>\r\n<div class="parrafo" align="justify">\r\nSintaxis:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>	ESTIMATE={BLOCKS | STATISTICS}\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nEjemplo:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>&gt; expdp hr/hr TABLES=employees \r\n				ESTIMATE=STATISTICS\r\n				DIRECTORY=dpump_dir1\r\n				DUMPFILE=estimate_stat.dmp\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\n<strong>5. ESTIMATE_ONLY</strong>: Si se configura a ''y'' indicamos que solo queremos una estimacion del espacio.\r\n</div>\r\n<div class="parrafo" align="justify">\r\n<strong>6. EXCLUDE</strong>: Lo podemos utilizar para excluir algunos elementos en nuestro export.\r\n</div>\r\n<div class="parrafo" align="justify">\r\nSintaxis:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>	EXCLUDE=object_type[:name_clause] [, ...]\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nEjemplo:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>	EXCLUDE=INDEX:"LIKE ''EMP%''"\r\n	EXCLUDE=SCHEMA:"=''HR''"\r\n\r\n&gt; expdp hr/hr DIRECTORY=dpump_dir1 DUMPFILE=hr_exclude.dmp EXCLUDE=VIEW,\r\nPACKAGE, FUNCTION\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\n<strong>7. FILESIZE</strong>: Tama&ntilde;o del fichero. Por defecto es 0 (ilimitado). Si se sobrepasase el espacio obtendriamos el siguietne error:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>ORA-39095: Dump file space has been exhausted: Unable to allocate 317088 bytes\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nSintaxis:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>	FILESIZE=integer[B | K | M | G]\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nEjemplo:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>&gt; expdp hr/hr DIRECTORY=dpump_dir1 DUMPFILE=hr_3m.dmp FILESIZE=3M\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\n<strong>8. INCLUDE</strong>: Indicamos que elementos tenemos que a&ntilde;adir en el export. En este caso no podemos utilizar un INCLUDE y un EXCLUDE juntos.\r\n</div>\r\n<div class="parrafo" align="justify">\r\nSintaxis:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>	INCLUDE = object_type[:name_clause] [, ...]\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nLa lista de los tipos de objetos que podemos a&ntilde;adir se pueden mirar en estas vistas:\r\n<div class="parrafo_lista_sub">\r\n- DATABASE_EXPORT_OBJECTS </br>\r\n- SCHEMA_EXPORT_OBJECTS </br>\r\n- TABLE_EXPORT_OBJECTS\r\n</div>\r\n</div>\r\n<div class="parrafo" align="justify">\r\nEjemplo:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>	SCHEMAS=HR\r\n	DUMPFILE=expinclude.dmp\r\n	DIRECTORY=dpump_dir1\r\n	LOGFILE=expinclude.log\r\n	INCLUDE=TABLE:"IN (''EMPLOYEES'', ''DEPARTMENTS'')"\r\n	INCLUDE=PROCEDURE\r\n	INCLUDE=INDEX:"LIKE ''EMP%''â€\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\n<strong>9. JOB_NAME</strong>: Por defecto es SYS_EXPORT_&lt;mode&gt;_NN (JOB_NAME=jobname_string) , lo podemos utilizar para ejecutar ATTACH.\r\n</div>\r\n<div class="parrafo" align="justify">\r\nSintaxis: \r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>JOB_NAME=jobname_string\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nEjemplo:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>&gt; expdp hr/hr DIRECTORY=dpump_dir1 \r\n				DUMPFILE=exp_job.dmp\r\n				JOB_NAME=exp_job\r\n				NOLOGFILE=y\r\n				\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\n<strong>10. LOGFILE</strong>: Nombre del log que nos deja. Por defecto export.log. Podemos utilizar el parametro NOLOGFILE=y para que no gener log.\r\n</div>\r\n<div class="parrafo" align="justify">\r\nSintaxis:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>LOGFILE=[directory_object:]file_name\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\n<strong>11. QUERY</strong>\r\n</div>\r\n<div class="parrafo" align="justify">\r\nSintaxis:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>QUERY = [schema.][table_name:] query_clause\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nEjemplo\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>QUERY=employees:''"WHERE department_id &gt; 10 AND salary &gt; 10000"''\r\n</p></pre></blockquote>'),
(66, '\r\n<h3>Ejemplo1: </h3>\r\n\r\n\r\n<div class="parrafo" align="justify">\r\nExportamos una tabla. Utilizamos NOLOGFILE=y para que deje log.\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>&gt;expdp hr/hr TABLES=employees,jobs DUMPFILE=dpump_dir1:table.dmp NOLOGFILE=y\r\n\r\n</p></pre></blockquote>\r\n<h3>Ejemplo 2: </h3>\r\n\r\n\r\n<div class="parrafo" align="justify">\r\nExportamos el esquema hr, excluyendo tablas y unicamente exportando los datos. Ademas para la tabla employees exportamos unicamente los datos que cumplen un determinado predicado.\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>Parfile exp.par:\r\n	DIRECTORY=dpump_dir1\r\n	DUMPFILE=dataonly.dmp\r\n	CONTENT=DATA_ONLY\r\n	EXCLUDE=TABLE:"IN (''COUNTRIES'', ''REGIONS'')"\r\n	QUERY=employees:"WHERE department_id !=50 ORDER BY employee_id"\r\n\r\n&gt; expdp hr/hr PARFILE=exp.par\r\n\r\n</p></pre></blockquote>\r\n<h3>Ejemplo 3:</h3>\r\n\r\n<div class="parrafo" align="justify">\r\nEstimamos el espacio que va a ocupar el export de tres tablas.\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>&gt; expdp hr/hr DIRECTORY=dpump_dir1 \r\n		ESTIMATE_ONLY=y \r\n		TABLES=employees,departments, locations\r\n		LOGFILE=estimate.log\r\n\r\n</p></pre></blockquote>\r\n<h3>Ejemplo 4:</h3>\r\n\r\n<div class="parrafo" align="justify">\r\nExport en paralelo de toda una base de datos. Tanto el job como la master table se llamara expfull\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>&gt; expdp hr/hr FULL=y \r\n		DUMPFILE=dpump_dir1:full1%U.dmp, dpump_dir2:full2%U.dmp\r\n		FILESIZE=2G \r\n		PARALLEL=3 \r\n		LOGFILE=dpump_dir1:expfull.log JOB_NAME=expfull\r\n</p></pre></blockquote>\r\n'),
(67, '<div class="parrafo" align="justify">\r\nPodemos elegir si importar los datos desde los ficheros dmp o directamente de la base de datos.\r\n</div>\r\n<div class="parrafo" align="justify">\r\nModos de trabajo:\r\n</div>\r\n<div class="parrafo" align="justify">\r\na)	<strong>Import full</strong>: Importamos el contenido total del export full. Tenemos que tener el role de IMP_FULL_DATABASE. \r\n</div>\r\n<div class="parrafo" align="justify">\r\nb)	<strong>Schema mode</strong>: Podemos importar unicamente un esquema de un export full o de un export de varios esquemas.\r\n</div>\r\n<div class="parrafo" align="justify">\r\nc)	<strong>Tablespace mode.</strong>\r\n</div>\r\n<div class="parrafo" align="justify">\r\nd)	<strong>Table mode</strong>: La fuente de los datos pueden ser cualquiera de los export anteriores.\r\n</div>\r\n<div class="parrafo" align="justify">\r\ne) <strong>Transportable Tablespace Mode</strong>: Sirve para hacer el import de los metadatos de un tablespace y la fuente tiene que ser un export del mismo tipo.\r\n</div>\r\n<h3>Comandos</h3>\r\n\r\n<div class="parrafo" align="justify">\r\n<strong>CONTENT</strong>: Indicamos que tipos de datos vamos a importar.\r\n</div>\r\n<div class="parrafo" align="justify">\r\nSintaxis:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>	CONTENT={ALL | DATA_ONLY | METADATA_ONLY}\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nEjemplo:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>	&gt; impdp hr/hr DIRECTORY=dpump_dir1 DUMPFILE=expfull.dmp CONTENT=METADATA_ONLY\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\n<strong>JOB_NAME</strong>: Para darle nombre al job y a la tabla maestra.\r\n</div>\r\n<div class="parrafo" align="justify">\r\nSintaxis: \r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>	JOB_NAME=jobname_string\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nEjemplo:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>	&gt; impdp hr/hr DIRECTORY=dpump_dir1 DUMPFILE=expfull.dmp JOB_NAME=impjob01\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\n<strong>QUERY</strong>: Dado un fichero de export podemos filtrar los datos con este comando.\r\n</div>\r\n<div class="parrafo" align="justify">\r\nSintaxis:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>	QUERY=[[schema_name.]table_name:]query_clause\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nEjemplo:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>	QUERY=departments:"WHERE department_id &lt; 120"\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\n<strong>REMAP_DATAFILE</strong>: Cambia el nombre del datafile\r\n</div>\r\n<div class="parrafo" align="justify">\r\nSintaxis:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>	REMAP_DATAFILE=source_datafile:target_datafile\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nEjemplo:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>	DIRECTORY=dpump_dir1\r\n	FULL=Y\r\n	DUMPFILE=db_full.dmp\r\n	REMAP_DATAFILE=''/db1/hrdata/tbs6.f'''':''/db1/hrdata/payroll/tbs6.f''\r\n	\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\n<strong>REMAP_SCHEMA</strong>: Importa los datos en otro esquema. Si el esquema destino no existe se crea, desde system tendremos que hacer un alter user para que nos podamos conectar.\r\n</div>\r\n<div class="parrafo" align="justify">\r\nEjemplo:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>	&gt; expdp SYSTEM/password \r\n		SCHEMAS=hr \r\n		DIRECTORY=dpump_dir1 \r\n		DUMPFILE=hr.dmp\r\n\r\n	&gt; impdp SYSTEM/password \r\n		DIRECTORY=dpump_dir1 \r\n		DUMPFILE=hr.dmp\r\n		REMAP_SCHEMA=hr:scott\r\n\r\n-- Si scott no existiese\r\nSQL&gt; ALTER USER scott IDENTIFIED BY temporal;\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\n<strong>REMAP_TABLESPACE</strong>: Cambiamos el tablespace de los objetos importados.\r\n</div>\r\n<div class="parrafo" align="justify">\r\nSintaxis:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>	REMAP_TABLESPACE=source_tablespace:target_tablespace\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\n<strong>SKIP_UNUSABLE_INDEXES</strong>: configurado a Y, si a la hora de importar algun indice de una tabla esta en estado unusable no se importa.\r\n</div>\r\n<div class="parrafo" align="justify">\r\n<strong>TABLE_EXISTS_ACTION</strong>: Acciones a tomar cuando encuentra la misma tabla en el destino.\r\n</div>\r\n<div class="parrafo" align="justify">\r\nSintaxis:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>	TABLE_EXISTS_ACTION={SKIP | APPEND | TRUNCATE | REPLACE}\r\n\r\n</p></pre></blockquote>\r\n<h3>Ejemplo 1: </h3>\r\n\r\n<div class="parrafo" align="justify">\r\nImportamos solo una tabla.\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>	&gt; impdp hr/hr TABLES=employees\r\n		CONTENT=DATA_ONLY \r\n		DUMPFILE=dpump_dir1:table.dmp\r\n		NOLOGFILE=y\r\n\r\n</p></pre></blockquote>\r\n<h3>Ejemplo 2:</h3>\r\n\r\n\r\n<div class="parrafo" align="justify">\r\nImportamos un esquema, excluyendo los indices y constraints.\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>&gt; impdp hr/hr SCHEMAS=hr \r\n		DIRECTORY=dpump_dir1 \r\n		DUMPFILE=expschema.dmp\r\n		EXCLUDE=CONSTRAINT,REF_CONSTRAINT,INDEX \r\n		TABLE_EXISTS_ACTION=REPLACE\r\n</p></pre></blockquote>'),
(68, '\r\n<div class="parrafo" align="justify">\r\nMe ocurrio el otro dia que uno de los scripts de mantenimiento que lanc&eacute; lo tuve que parar para evitar que se metiese en hora de alto trafico. Os explico como lo hice:\r\n</div>\r\n<div class="parrafo" align="justify">\r\n1. Identifico el PID del script ksh y de proceso sqlplus que lanza ese script.\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>&gt; ps -fea | grep 03_Purga_tabla.ksh\r\n\r\noracle    8198  9738  0 01:59 pts/0    00:00:00 /bin/ksh ./03_Purga_tabla.ksh \r\n\r\n&gt; ps -fea | grep 8198\r\n\r\noracle    8198  9738  0 01:59 pts/0    00:00:00 /bin/ksh ./03_Purga_tabla.ksh \r\noracle    8222  8198  0 01:59 pts/0    00:00:00 /softw/app/oracle/product/10.2.0/db/bin/sqlplus -s    \r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\n2. Paramos el script de ksh\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>&gt; kill -9 8198 (Un poco a lo bruto :-)\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\n3. Antes de parar vamos a obtener informacion de la sesion de sqlplus.\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>SELECT '' sid, serial#, aud sid : ''|| s.sid||'' , ''||s.serial#||'' , ''||\r\n      s.audsid||chr(10)|| ''DB User / OS User : ''||s.username||\r\n      ''   /   ''||s.osuser||chr(10)|| ''Machine - Terminal : ''||\r\n      s.machine||''  -  ''|| s.terminal||chr(10)||\r\n      ''OS Process Ids : ''|| s.process||'' (Client)  ''||chr(10)||\r\n      ''Client Program Name : ''||s.program "Session Info"\r\nFROM GV$SESSION S WHERE s.process=''8222'';\r\n\r\nSession Info\r\n--------------------------------------------------------------------------------\r\nsid, serial#, aud sid : 1332 , 774 , 34519093\r\nDB User / OS User : OPGE    /   oracle\r\nMachine - Terminal : bogbesg6  -\r\nOS Process Ids : 8222 (Client)\r\nClient Program Name : sqlplus@bogbesg6 (TNS V1-V3)\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nCon este script obtenemos la informacion de la sesion, a destacar el sid y el serial, el usuario que de base de datos y el de sistema operativo, la maquina y cliente utilizado y el PID del proceso.\r\n</div>\r\n<div class="parrafo" align="justify">\r\n4. Por curiosidad vemos que sentencia esta ejecutando esa sesision.\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>SQL&gt; SELECT\r\n	SID, SQL_TEXT\r\nFROM\r\n	V$SESSION A, V$SQL B\r\nWHERE\r\n	A.SQL_HASH_VALUE=B.HASH_VALUE AND\r\n	A.SID=''1332'';\r\n\r\nSID        	SQL_TEXT\r\n----------  --------------------------------------------------------------------------------\r\n1332        CREATE TABLE AUX_POGE_CAMBESTBOLSAS AS SELECT /*+\r\n			PARALLEL(POGE_CAMBESTBOLSAS,16) */ * FROM\r\n			POGE_CAMBESTBOLSAS\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\n5. Una vez asegurados matamos la sesion.\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>SQL&gt; ALTER SYSTEM KILL SESSION ''1332,774'';\r\n\r\nSystem altered.\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nY problema resuelto.\r\n</div>'),
(69, '<div class="parrafo" align="justify">\r\nPresentamos este script para obtener los bloqueos que se estan produciendo en nuestra bas ed de datos. Para entender este script es bueno leerse esta entrada.\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>select  l.sid,s.serial#,s.username,s.terminal,\r\n       decode(l.type,''RW'',''RW - Row Wait Enqueue'',\r\n                   ''TM'',''TM - DML Enqueue'',\r\n                   ''TX'',''TX - Trans Enqueue'',\r\n                   ''UL'',''UL - User'',l.type||''System'') res,\r\n       substr(t.name,1,10) tab,u.name owner,\r\n       l.id1,l.id2,\r\n       decode(l.lmode,1,''No Lock'',\r\n               2,''Row Share'',\r\n               3,''Row Exclusive'',\r\n               4,''Share'',\r\n               5,''Shr Row Excl'',\r\n               6,''Exclusive'',null) lmode,\r\n       decode(l.request,1,''No Lock'',\r\n               2,''Row Share'',\r\n               3,''Row Excl'',\r\n               4,''Share'',\r\n               5,''Shr Row Excl'',\r\n               6,''Exclusive'',null) request\r\n	from v$lock l, v$session s,\r\n	sys.user$ u,sys.obj$ t\r\n	where l.sid = s.sid\r\n	and s.type != ''BACKGROUND''\r\n	and t.obj# = l.id1\r\n	and u.user# = t.owner#\r\n	/\r\nset feedback on\r\n\r\nSalida:\r\n\r\n  SID SERIAL# USERNAME   Term   Resource Type        TAB        OWNER         ID1      ID2 Lock Held      Lock Req.\r\n-------- --------- ------------ -------- ---------------------- ------------ ---------- ---------- ---------- ---------------- ----------------\r\n 2044   59892 PPCS       pts/2  TM - DML Enqueue     AUX_CDR    PPCS        66816        0 Row Exclusive\r\n 2059   13335 PPCS       pts/1  TM - DML Enqueue     AUX_CDR    PPCS        66816        0 Row Exclusive\r\n\r\n</p></pre></blockquote>'),
(70, '<div class="parrafo" align="justify">\r\n1. Creamos una tabla de prueba y a&ntilde;adimos entradas.\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>SQL&gt; CREATE TABLE AUX_MSISDN (ID_MSISDN NUMBER(6));\r\n\r\nTable created.\r\n\r\nSQL&gt; INSERT INTO AUX_MSISDN VALUES (1);\r\nSQL&gt; INSERT INTO AUX_MSISDN VALUES (2);\r\nSQL&gt; INSERT INTO AUX_MSISDN VALUES (3);\r\nSQL&gt; INSERT INTO AUX_MSISDN VALUES (4);\r\nSQL&gt; INSERT INTO AUX_MSISDN VALUES (5);\r\nSQL&gt; INSERT INTO AUX_MSISDN VALUES (6);\r\nSQL&gt; INSERT INTO AUX_MSISDN VALUES (7);\r\n\r\nSQL&gt; commit;\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\n2. Actualizamos un registro sin realizar commit y vemos que bloqueo crea.\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>SQL&gt; UPDATE AUX_MSISDN SET ID_MSISDN=2 WHERE ID_MSISDN=1;\r\n\r\n1 row updated.\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\n3. Revisamos la tabla v$lock\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>SQL&gt; SELECT SID, TYPE, ID1, ID2, LMODE, REQUEST, CTIME FROM V$LOCK;\r\n\r\nSQL&gt; SELECT SID, TYPE, ID1, ID2, LMODE, REQUEST, CTIME FROM V$LOCK;\r\n\r\nSID 	TY  ID1         ID2  	LMODE     REQUEST  CTIME\r\n---------- ---- ---------- ---------- --------------- ---------------- ----------\r\n2093 	TM  82416     	0		3		0      	    220\r\n2093 	TX   2293798 	44976	6		0    	    220\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nEs logico que se adquieran dos bloqueos, uno a nivel de transaccion TX y otro a nivel de sentencia DML TM.\r\n\r\n</div>\r\n<div class="parrafo" align="justify">\r\n4. Desde una segunda sesion intentamos actualizar la misma fila que se actualizo en la primera.\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>SQL&gt; UPDATE AUX_MSISDN SET ID_MSISDN=3 WHERE ID_MSISDN=1;\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nAl ejecutar vemos que la query no nos devuelve el control del cursor. Volvemos a mirar que bloqueos tenemos:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>SQL&gt; SELECT SID, TYPE, ID1, ID2, LMODE, REQUEST, CTIME FROM V$LOCK;\r\n\r\nSID 	TY  ID1         ID2  	LMODE     REQUEST  CTIME\r\n---------- ---- ---------- ---------- --------------- ---------------- ----------\r\n1984 TM	82416      	0		3      	0     	87\r\n1984 TX	2293798  	44976	0      	6     	87\r\n2093 TM	82416      	0		3      	0   	3111\r\n2093 TX	2293798  	44976	6      	0   	3111\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nComo vemos que introduce dos bloqueos mas pero en uno de ellos TX se ve que estaesperando. El otro es porque ha ejecutado una sentencia DML.\r\n</div>\r\n<div class="parrafo" align="justify">\r\nRevisamos en v$SESSION_WAIT que ha pasado con esta sesion:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>SQL&gt; SELECT EVENT FROM V$SESSION_WAIT WHERE SID=1984;\r\n\r\nEVENT\r\n----------------------------------------------------------------\r\nenq: TX - row lock contention\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nNos indica que es debido a un bloqueo de la fila.\r\n</div>\r\n<div class="parrafo" align="justify">\r\n5. Liberamos el bloqueo de la primera sesion\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>SQL&gt; SELECT SID, TYPE, ID1, ID2, LMODE, REQUEST, CTIME FROM V$LOCK ORDER BY SID;\r\n\r\nSID 	TY  ID1	ID2  	LMODE   REQUEST  CTIME\r\n---------- ---- ------------ 	---------- ------------ -------------   -------------\r\n1984 	TM 82416      	0      	3      	     0   	     	  2248\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nSigue manteniendo el bloqueo TM. El TX no se mantiene por que estabamos haciendo el update sobre la misma columna del predicado.\r\n</div>\r\n');
INSERT INTO `ENTRADA_TEXTO` (`ID_ENTRADA`, `TEXTO`) VALUES
(71, '<div class="parrafo" align="justify">\r\nAnte un bloqueo Oracle serializa el acceso al objeto, de tal forma que a un proceso le quedara esperar hasta que el primero termine.\r\n</div>\r\n<h3>Tipos de bloqueo:</h3>\r\n\r\n<div class="parrafo_lista_sub">\r\nTX: Bloqueos de transacciones. Bloqueos que se producen cuando una transaccion esta intentando modificar datos.</br>\r\nTM: Bloqueos que se dan durante sentencias DML.</br>\r\nUL: Bloqueos definidos por el usuario.</br>\r\n</div>\r\n\r\n<h3>Modos de bloqueo:</h3>\r\n\r\n\r\n<div class="parrafo_lista_sub">\r\nRow Shared (RS): Bloquea unicamente las filas que esta intentando actualizar, Evita que se realce el bloqueo de la tabla en  exclusivo y compartido.</br>\r\nRow Exclusive (RX): Unicamente bloque la fila que esta utilizando la transaccion. Evita que se produzcan bloqueos de la tabla en modo exclusivo.</br>\r\nShare (S): Se ejecuta de forma explicita ejecutando LOCK TABLE &lt;table&gt; IN SHARE MODE;</br>\r\nShare Row Exclusive (SRX/SSX)</br>\r\nExclusive (X)</br>\r\n</div>\r\n<div class="parrafo" align="justify">\r\nPara saber si tenemos bloqueos en nuestra base de datos utilizaremos la vista v$lock.\r\nLas columnas de la tabla son:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p> 		Name               Type\r\n		 -------------------- ----------------------------\r\n		 ADDR              RAW(8)\r\n		 KADDR            RAW(8)\r\n		 SID                   NUMBER\r\n		 TYPE               VARCHAR2(2)\r\n		 ID1                   NUMBER\r\n		 ID2                   NUMBER\r\n		 LMODE            NUMBER\r\n		 REQUEST       NUMBER\r\n		 CTIME             NUMBER\r\n		 BLOCK            NUMBER\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nLas columnas mas interesantes son: </br>\r\n- SID: identifica la sesion que genera el bloque o esta esperando.</br>\r\n- TYPE: tipos de bloqueo que obtenemos.\r\n<div class="parrafo_lista_sub">\r\n	TM </br>\r\n	TX</br>\r\n	UL\r\n</div>\r\n\r\n- LMODE: Si lmode es distinto de 0 o 1 esa sesion esta generando un bloqueo. Los posibles valores que puede tener lmode son:</br>\r\n<div class="parrafo_lista_sub">\r\n	1: no hay bloqueo.</br>\r\n	2: Row Share (SS).</br>\r\n	3: Row Exclusive (SX).</br>\r\n	4: Share (S).</br>\r\n	5: Share Row Exclusive (SSX).</br>\r\n	6: Exclusive (X).</br>\r\n</div>\r\n\r\n- REQUEST: Si request tiene un valor diferente de 0 o 1 es que esta esperando a que se libere un recurso. El tipo de bloqueo que presenta se decodifica de la misma manera que LMODE.</br>\r\n\r\n- ID1: Si el tipo de bloqueo es TM ID1 es el ID del objeto bloqueado. Para saber el nombre del objeto bloqueado podemos hacer la query:\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>\r\n	SQL&gt; select name from dba_objects where OBJECT_ID=&object_id;\r\n\r\n</p></pre></blockquote>\r\n\r\n- CTIME: Tiempo desde que el actual estado fue adquirido.\r\n</div>\r\n<div class="parrafo" align="justify">\r\nEn este post podemos ver un script de monitoreo de bloqueos un poco mas completo.\r\n</div>'),
(72, '<div class="parrafo" align="justify">\r\nPodemos utilizar Flash Recovery Area junto con RMAN para dejar en manos de Oracle la gestion de los ficheros que se creen en esa zona. Oracle recomienda utilizar Flash Recovery Area unicamente para labores de backup.\r\n</div>\r\n<div class="parrafo" align="justify">\r\nDebemos de poner la Flash recovery area en un path diferente de los datafiles.\r\n</div>\r\n<div class="parrafo" align="justify">\r\nLos ficheros que pueden ser almacenados en la Flash Recovery Area se puden clasificar en dos tipos: permanentes y transitorios. Permanentes son las copias multiplexadas de los control files y de los online redo logs. Estos ficheros no se pueden borrar sin que la base de datos falle. Los ficheros transitorioes se borran automaticamente por Oracle una vez se conviertan en obsoletos. Archivos transitorios pueden ser los archive log, copias de datafiles, control files autobackups y backup pieces.\r\n</div>\r\n<div class="parrafo" align="justify">\r\nPara saber la cuota de espacio destinada a Flash Recovery Area podemos consultar la vista: V$RECOVERY_FILE_DEST.\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>SQL&gt; SELECT * FROM V$RECOVERY_FILE_DEST;\r\n\r\nNAME			SPACE_LIMIT		SPACE_USED	SPACE_RECLAIMABLE	NUMBER_OF_FILES\r\n-------------------------------------------------------------------------------------------------------------------------------------\r\n/mydisk/rcva		5368709120		109240320		256000		28\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nPara habilitar Flash Recovery Area tenemos que habilitar estos dos parametros:\r\n</div>\r\n<div class="parrafo" align="justify">\r\nDB_RECOVERY_FILE_DEST_SIZE: Indica la quota (bytes) de espacio para los ficheros que se alojan en la Flash Recovery Area.\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>SQL&gt; ALTER SYSTEM SET\r\n	DB_RECOVERY_FILE_DEST_SIZE = 10G\r\n	SCOPE=BOTH SID=''*'';\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nDB_RECOVERY_FILE_DEST: Indica donde se encuentra la Flash Recovery Area.\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>SQL&gt; ALTER SYSTEM SET\r\n	DB_RECOVERY_FILE_DEST = ''/disk1/flash_recovery_area''\r\n	SCOPE=BOTH SID=''*'';\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nEl hecho de utilizar Flash Recovery Area tiene algunas implicaciones en los parametros de inicializacion:\r\n</div>\r\n<div class="parrafo" align="justify">\r\n- Para indicar el destino de los archived redo log tendremos que utilizar los parametros LOG_ARCHIVE_DEST_n\r\n</div>\r\n<div class="parrafo" align="justify">\r\nPara deshabilitar la Flash Recovery Area unicamente tendremos que dejar en blanco uno de estos parametros:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>SQL&gt; show parameter db_recovery \r\n\r\nNAME				VALUE\r\n-------------------------------- ------------------------------\r\ndb_recovery_file_dest		/flash_recovery_area\r\ndb_recovery_file_dest_size		4G\r\n\r\nSQL&gt; alter system set db_recovery_file_dest='' '' scope=both sid=''*''; \r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nPodemos cambiar la ubicacion de la Flash Recovery Area haciendo:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>SQL&gt; ALTER SYSTEM SET DB_RECOVERY_FILE_DEST=''+disk1'' SCOPE=BOTH SID=''*'';\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nLos nuevo ficheros se crearan en la nueva ubicacion, no es necesario que cambiemos los ficheros permanentes de la vieja ubicacion, y los ficheros transitorios se iran borrando segun se vayan quedando obsoletos.\r\n</div>\r\n<div class="parrafo" align="justify">\r\nPara habilitar que los ficheros de las herramientas de Flashback se vayan generando en la nueva ubicacion es necesario hacer:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>		- Shutdown the Database\r\n		- Startup mount the Database:\r\n		  SQL&gt; startup mount;\r\n		- Toggle the Flashback off:\r\n		  SQL&gt; alter database flashback off;\r\n		- Toggle the Flashback on:\r\n		  SQL&gt; alter database flashback on;\r\n		- Open the Database:\r\n		  SQL&gt; alter database open;\r\n		  \r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nSi tuviesemos la necesidad de mover los ficheros permanentes y los backups set creados de la vieja ubicacion hariamos:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>  RMAN&gt; BACKUP AS COPY ARCHIVELOG ALL DELETE INPUT;\r\n  RMAN&gt; BACKUP DEVICE TYPE DISK BACKUPSET ALL DELETE INPUT;\r\n  \r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nPara mover las copias de los datafiles:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>RMAN&gt; BACKUP AS COPY DATAFILECOPY &lt;name&gt; DELETE INPUT;\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\n\r\nPara mover los controlfiles a la nueva ubicacion haremos, cambiamos el parametro de ubicacion de los control file y reiniciamos la base de datos dejandola en NOMOUNT. Luego ejecutamos:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>RMAN&gt; RESTORE CONTROLFILE FROM ''filename_of_old_control_file'';\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nPara mover los redo log, tendremos que a&ntilde;adir un nuevo fichero en la nueva Flash Recovery Area y borrar los viejos.\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>SQL&gt; alter database add logfile size 100M;\r\nSQL&gt; alter database drop logfile ''name of the old redo log'';\r\n\r\n</p></pre></blockquote>\r\n<div class="parrafo" align="justify">\r\nOracle propone la siguiente formula para calcular el espacio que deberiamos configurar para Flashback Recovery Area:\r\n</div>\r\n<blockquote style="COLOR: #2e5348; FONT-SIZE: 12px; FONT-WEIGHT: bold FONT:Arial, Helvetica, sans-serif">\r\n<pre><p>Quota=\r\n	Backup de una copia de la base de datos +\r\n	Tama&ntilde;o de un backup incremental	+\r\n	Tama&ntilde;o de (n+1) dias de archived log  +\r\n	Tama&ntilde;o de (y+1) dias archived log para la base de datos de standby  +\r\n	Tama&ntilde;o del control file  +\r\n	Tama&ntilde;o de los online redo log member\r\n</p></pre></blockquote>');

-- --------------------------------------------------------

--
-- Estructura de tabla para la tabla `SUBCATEGORIAS`
--

CREATE TABLE IF NOT EXISTS `SUBCATEGORIAS` (
  `ID_SUBCATEGORIA` tinyint(3) NOT NULL auto_increment,
  `ID_CATEGORIA` tinyint(3) NOT NULL,
  `SUBCATEGORIA` varchar(25) character set utf8 NOT NULL,
  PRIMARY KEY  (`ID_SUBCATEGORIA`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=52 ;

--
-- Volcar la base de datos para la tabla `SUBCATEGORIAS`
--

INSERT INTO `SUBCATEGORIAS` (`ID_SUBCATEGORIA`, `ID_CATEGORIA`, `SUBCATEGORIA`) VALUES
(33, 4, 'DDL'),
(35, 5, 'Ficheros'),
(36, 6, 'DataPump'),
(37, 5, 'Recursos'),
(38, 8, 'Generales'),
(39, 8, 'Monitorizar'),
(40, 4, 'Objetos'),
(41, 4, 'DML'),
(42, 8, 'Informacion'),
(43, 3, 'Objetos'),
(44, 3, 'Sintaxis'),
(45, 3, 'Tunning'),
(46, 3, 'DML'),
(47, 8, 'Solucionar Problemas'),
(48, 4, 'Ejemplos'),
(49, 6, 'Troubleshooting'),
(50, 6, 'Teoria'),
(51, 6, 'Objetos');

-- --------------------------------------------------------

--
-- Estructura de tabla para la tabla `TAGS`
--

CREATE TABLE IF NOT EXISTS `TAGS` (
  `ID_TAG` tinyint(3) NOT NULL auto_increment,
  `TAG` varchar(50) character set utf8 NOT NULL,
  PRIMARY KEY  (`ID_TAG`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=37 ;

--
-- Volcar la base de datos para la tabla `TAGS`
--

INSERT INTO `TAGS` (`ID_TAG`, `TAG`) VALUES
(15, 'Secuencias'),
(16, 'Ficheros'),
(17, 'Filesystem'),
(18, 'Disco'),
(19, 'Objetos'),
(20, 'Export'),
(21, 'Rendimiento'),
(22, 'LOGs'),
(23, 'SQLPlus'),
(24, 'Bucles'),
(25, 'Constraints'),
(26, 'Cursores'),
(27, 'Estructuras control'),
(28, 'Indices'),
(29, 'Tunning'),
(30, 'Paquetes'),
(31, 'Errores'),
(32, 'Import'),
(33, 'Procesos'),
(34, 'Sesiones'),
(35, 'Bloqueos'),
(36, 'RMAN');

-- --------------------------------------------------------

--
-- Estructura de tabla para la tabla `USER_STATUS`
--

CREATE TABLE IF NOT EXISTS `USER_STATUS` (
  `ID_STATUS` tinyint(2) NOT NULL,
  `STATUS` varchar(25) character set utf8 NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

--
-- Volcar la base de datos para la tabla `USER_STATUS`
--

INSERT INTO `USER_STATUS` (`ID_STATUS`, `STATUS`) VALUES
(2, 'USER'),
(1, 'ADMIN');

-- --------------------------------------------------------

--
-- Estructura de tabla para la tabla `USUARIOS`
--

CREATE TABLE IF NOT EXISTS `USUARIOS` (
  `ID_USUARIO` tinyint(3) NOT NULL,
  `USUARIO` varchar(25) character set utf8 NOT NULL,
  `PASS` varchar(100) character set utf8 NOT NULL,
  `ID_STATUS` tinyint(2) NOT NULL,
  `ACTIVO` tinyint(1) NOT NULL,
  PRIMARY KEY  (`ID_USUARIO`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

--
-- Volcar la base de datos para la tabla `USUARIOS`
--

INSERT INTO `USUARIOS` (`ID_USUARIO`, `USUARIO`, `PASS`, `ID_STATUS`, `ACTIVO`) VALUES
(1, 'LUISMI', '95964d35e40f97df2a2b849151772d11', 1, 0),
(2, 'JPRIETO', '6a552e8af99d6466a44b4a20ed0ee3f5', 1, 0),
(3, 'A', '0cc175b9c0f1b6a831c399e269772661', 1, 0);
